0

I am attempting to serialize/deserialze an object using the System.Text.Json JsonSerializer. My container object is a "LicenseFile" which contains a "License" object along with a byte[] digital signature.

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; }
}

When serializing the LicenseFile, I would also like to first convert the License values to JSON and afterwards Base64. To do this, I created a custom JSON converter e.g.

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();
    }
}

I would like to end up with a JSON output something like this:

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

My questions:

  1. Is this a good approach? Would I better off to just use helper methods to serialize the values first, base64 them and then write them out to a file?
  2. How can I deserialze the JSON object back into objects again (while de-base64'ing them on the way)

Thanks for any recommendations!

bdan
  • 91
  • 1
  • 5
  • `System.Text.Json.JsonSerializer` will already serialize a `byte []` array as a Base64 string, see [The JSON value could not be converted to `System.Byte[]`](https://stackoverflow.com/a/61566219/3744182). But why do you need to convert `License` to Base64? It's not like Base64 encoding actually provides any meaningful encryption, obfuscation or parity checking. – dbc May 06 '21 at 17:42
  • I'm using Base64 just to prevent casual readability, not for any kind of security. Mostly interested in the general technique of how to get in between the serialization request, and the end result. – bdan May 08 '21 at 17:37

1 Answers1

0

I recommend:

  1. a dedicated Dto; or
  2. [JsonIgnore] on License and an auxiliary field;

For example:

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; }
}

or

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

Test

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://learn.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"
}
tymtam
  • 31,798
  • 8
  • 86
  • 126