首页 > 解决方案 > 使用嵌套对象和中间步骤进行反序列化

问题描述

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

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[]"
}

我的问题:

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

感谢您的任何建议!

标签: c#base64jsonserializersystem.text.json

解决方案


我建议:

  1. 一个专用的 Dto;或者
  2. [JsonIgnore]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"
}

推荐阅读