使用嵌套对象和中间步骤进行反序列化

Posted

技术标签:

【中文标题】使用嵌套对象和中间步骤进行反序列化【英文标题】:Deserialization with nested object and in-between step 【发布时间】:2021-07-29 01:32:30 【问题描述】:

我正在尝试使用 System.Text.Json JsonSerializer 序列化/反序列化对象。 我的容器对象是一个“LicenseFile”,其中包含一个“License”对象以及一个 byte[] 数字签名。

public class LicenseFile

    public License License  get; set; 
    public byte[] Signature  get; set; 


public class License

    public string ProductName  get; set; 
    public string ProductVersion  get; set; 

在序列化 LicenseFile 时,我还想先将 License 值转换为 JSON,然后再转换为 Base64。 为此,我创建了一个自定义 JSON 转换器,例如

public class LicenseFileConverter : JsonConverter<LicenseFile>

    public override void Write(Utf8JsonWriter writer, LicenseFile licenseFile, JsonSerializerOptions options)
    
        writer.WriteStartObject();
        var json = JsonSerializer.Serialize(licenseFile.License);
        byte[] jsonBytes = new UTF8Encoding().GetBytes(json);
        writer.WriteBase64String("License", jsonBytes);
        writer.WriteBase64String("Signature", licenseFile.Signature);
        writer.WriteEndObject();
        writer.Flush();
    

我希望得到类似这样的 JSON 输出:


  "License": "BASE64_OF_LICENSE_OBJECT_JSON'D",
  "Signature": "BASE64_OF_SIGNATURE_BYTE[]"

我的问题:

    这是一个好方法吗?我最好只使用辅助方法先序列化值,base64 它们然后将它们写出到文件中? 如何将 JSON 对象反序列化回对象(同时在途中对它们进行 de-base64)

感谢您的任何建议!

【问题讨论】:

System.Text.Json.JsonSerializer 已经将byte [] 数组序列化为 Base64 字符串,请参阅The JSON value could not be converted to System.Byte[]。但是为什么需要将License 转换为Base64?它不像 Base64 编码实际上提供任何有意义的加密、混淆或奇偶校验。 我使用 Base64 只是为了防止偶然的可读性,而不是为了任何安全性。主要对如何在序列化请求和最终结果之间介入的一般技术感兴趣。 【参考方案1】:

我推荐:

    专用 Dto;或 [JsonIgnore] on License 和一个辅助字段;

例如:

public class LicenseFile

    [JsonIgnore]
    public License License  get; set; 

    public string LicenseJson => JsonSerializer.Serialize(License); // Add base64 encoding if you wish

    public byte[] Signature  get; set; 

public class LicenseFileDto

    public LicenseFileDto(LicenseFile license) 
        License = JsonSerializer.Serialize(license.License);
        Signature = license.Signature;
    
    public string License  get; 
    public byte[] Signature  get; 

测试

var l = new LicenseFile

    License = new License(name: "X Y", validUntil: new DateTime(2021, 04, 22)),
    Signature = new byte[]  1, 2, 3 
;

var json = JsonSerializer.Serialize(l, 
    options: new JsonSerializerOptions  WriteIndented = true );
Console.WriteLine(json);

var dtoJson = JsonSerializer.Serialize(new LicenseFileDto(l), 
    options: new JsonSerializerOptions  WriteIndented = true );
Console.WriteLine(dtoJson);            

// Documentation at:
//   https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-character-encoding#serialize-all-characters
// says: 
//     Use the unsafe encoder only when it's known that the client will be interpreting the resulting payload as UTF-8 encoded JSON.
var prettyJson = JsonSerializer.Serialize(new LicenseFileDto(l), 
    options: new JsonSerializerOptions  WriteIndented = true, Encoder = javascriptEncoder.UnsafeRelaxedJsonEscaping );
Console.WriteLine(prettyJson);

  "LicenseJson": "\u0022Name\u0022:\u0022X Y\u0022,\u0022ValidUntil\u0022:\u00222021-04-22T00:00:00\u0022",
  "Signature": "AQID"


  "License": "\u0022Name\u0022:\u0022X Y\u0022,\u0022ValidUntil\u0022:\u00222021-04-22T00:00:00\u0022",
  "Signature": "AQID"


  "License": "\"Name\":\"X Y\",\"ValidUntil\":\"2021-04-22T00:00:00\"",
  "Signature": "AQID"

【讨论】:

以上是关于使用嵌套对象和中间步骤进行反序列化的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 protobuf-net 序列化/反序列化锯齿状/嵌套数组?

什么是java的序列化和反序列化?

使用 RestTemplate 反序列化嵌套对象

什么是json的序列化和反序列化

C# json反序列化 对象中嵌套数组 (转载)

Java - 如何反序列化带有嵌套对象和列表的 JSON 数组? [复制]