Search code examples
c#asp.net.netsystem.text.json

How can I serialize a literal JSON value with System.Text.Json?


I have a class in C# 6, something like the following:

public class Foo {
   public string Name { get; set; }
   public string OtherStuff { get; set; }
}

The OtherStuff property is a known-valid JSON-encoded string.

I'm trying to return this class from an API method, using the default System.Text.Json serializer. But I want OtherStuff to be written out literally, not escaped into a string value.

Things I've tried:

  • Looked in JsonSerializerOptions for something to do this.
  • Tried using System.Text.Json.Nodes.JsonNode instead of string. It still emits the value as a string.
  • Tried writing a custom JsonConverter, but the Write() method takes in Utf8JsonWriter, which does not appear to have a way to write a string as a literal value, only ways to write a string as a JSON string.
public class LiteralJsonConverter : JsonConverter<string> {
  public override string Read(ref Utf8JsonReader reader, 
                              Type typeToConvert, 
                              JsonSerializerOptions options)
       => reader.GetString();

  public override void Write(Utf8JsonWriter writer, 
                             string value, 
                             JsonSerializerOptions options)
      => writer.WriteStringValue(value); // Can't find a method to
                                         // write a pre-encoded value
}

I want to avoid having to parse this string from JSON into an object just so I can re-emit it in JSON. It's a JSON string in my database, and the data model is opaque to the API.

Can anyone suggest a solution?


Solution

  • System.Text.Json supports this starting from version 6, the method is called WriteRawValue:

    public class LiteralJsonConverter : JsonConverter<string>
    {
      public override string Read(ref Utf8JsonReader reader, 
                                  Type typeToConvert, 
                                  JsonSerializerOptions options)
                                  => reader.GetString();
    
      public override void Write(Utf8JsonWriter writer, 
                                 string value, 
                                 JsonSerializerOptions options) 
                                 => writer.WriteRawValue(value);        
    }
    

    If you are on .NET 6 then it's available by default. Otherwise you can install nuget package System.Text.Json of version 6 to get access to this functionality (this package supports .NET Standard so can be used even in old .NET 4).

    Note that it accepts second parameter: skipInputValidation, so for even more perfomance, if you are sure what you are writing is valid json - you can skip that and use WriteRawValue(value, true).