0

I am trying to write a custom JsonConverter and it works - I can read it back in a valid object, but json indentation is messed up.

public override void WriteJson(JsonWriter writer, IJsonProperty<TModel> value, JsonSerializer serializer)
{
    writer.Formatting = Formatting.Indented;
    writer.WriteRawValue((string)value.Data); // value.Data contains a json string
}

The result is missing indentation.

{
  "$type": "PAServer.data.BehaviorModel, PAServer",
  "Behavior": {
  "$type": "PAShared.data.BehaviorModel, PAShared", // - this should be indented
  //stuff
}, // - note the closing brace...
  "Name": "Empty"
}

This is how I call serialize:

var json = JsonConvert.SerializeObject(this, Formatting.Indented,
                    new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All });

How do I indent data in writer.WriteRawValue((string)value.Data);?

Brian Rogers
  • 125,747
  • 31
  • 299
  • 300
Chebz
  • 1,375
  • 3
  • 14
  • 27

1 Answers1

0

JsonWriter.WriteRawValue(string) does what the documentation says and no more.

Writes raw JSON where a value is expected and updates the writer's state.

It doesn't attempt to parse, modify, or otherwise format the incoming JSON. In fact you can use WriteRawValue() to write malformed JSON if you really want to, see e.g. Create invalid Json with Newtonsoft - Allow invalid objects?.

If you want to reformat the raw JSON to match the current indentation of the JSON being written, you will need to tokenize it and write out each token using the following extension method:

public static class JsonExtensions
{
    public static void WriteFormattedRawValue(this JsonWriter writer, string json, DateParseHandling dateParseHandling = DateParseHandling.None, FloatParseHandling floatParseHandling = default)
    {
        if (json == null)
            writer.WriteRawValue(json);
        else
            using (var reader = new JsonTextReader(new StringReader(json)) { DateParseHandling = dateParseHandling, FloatParseHandling = floatParseHandling })
                writer.WriteToken(reader);
    }
}

Which can be called as follows:

public override void WriteJson(JsonWriter writer, IJsonProperty<TModel> value, JsonSerializer serializer) =>
    writer.WriteFormattedRawValue((string)value.Data);

Note that JsonTextReader recognizes and parses floating point numbers as well as dates and times, so there is a chance that the raw JSON's values may get modified in the process. Setting DateParseHandling.None disables recognition of date/time strings, but you may still need to control whether to parse floating-point numbers as decimal or double by setting FloatFormatHandling.

Demo fiddle here.

dbc
  • 104,963
  • 20
  • 228
  • 340