1

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?

richardtallent
  • 34,724
  • 14
  • 83
  • 123

1 Answers1

3

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).

Evk
  • 98,527
  • 8
  • 141
  • 191
  • This is perfect, thanks! I have no idea how I missed that in the method list. I must've looked at it 20 times. – richardtallent Nov 11 '21 at 14:58
  • This works perfectly for writing but `reader.GetString();` will only read a JSON value which is actually a string primitive. To read an arbitrary JSON value of any type then return it as a string I think you need to load it into a `JsonDocument` and return the raw text (being sure to dispose the `JsonDocument`). See e.g. [Is there an equivalent for JRaw in System.Text.Json](https://stackoverflow.com/a/70477321/3744182). – dbc Sep 13 '22 at 18:31