2

I'm reading a large object which contains thousands of sub-objects that I don't want to deserialize into full C# objects (for performance reasons) but just load them as dummy wrapper objects to keep their JSON as strings (for later phase where they are serialized again).
So far I have the following concept code (not final), but I would prefer to avoid the JObject creation and just read somehow the sub-objects string straight from the reader into the wrapper json member string. Is there an easy way to do so without switching over all possible tokens and reading them one by one?

namespace Playground
{
    [JsonConverter(typeof(ObjectJsonWrapperConverter))]

    public class ObjectJsonWrapper
    {
        public string Json;
    }

    public class ObjectJsonWrapperConverter : JsonConverter
    {
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            writer.WriteRawValue(((ObjectJsonWrapper)value).Json);
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            var wrapper=new ObjectJsonWrapper();
            if (reader.TokenType == JsonToken.Null)
            {
                return null;
            }
            else if (reader.TokenType == JsonToken.StartObject)
            {
                var obj=JsonConvert.SerializeObject(JObject.Load(reader));
                wrapper.Json = obj;
                return wrapper;
            }
            else
            {
                throw new ArgumentException("Bad parsing");
            }
        }

        public override bool CanConvert(Type objectType)
        {
            throw new NotImplementedException();
        }
    }
}
Avner Levy
  • 6,601
  • 9
  • 53
  • 92
  • Looks like a duplicate of [Efficiently get full json string in JsonConverter.ReadJson()](https://stackoverflow.com/q/56944160/3744182). However, you may actually get better memory performance if you deserialize to some typed data model than keep around some huge string that will end up on the large object heap. (I agree you shouldn't use a `JToken` hierarchy, doing so probably will use lots of memory for property names.) – dbc Apr 19 '20 at 03:43

1 Answers1

3

If I understand you correctly, what you are looking for is persisting content of JsonReader as string, and that's what JRaw does.

class ObjectJsonWrapperConverter : JsonConverter
{
    public override bool CanConvert(Type objectType) => true;

    public override object ReadJson(JsonReader reader, Type objectType, 
        object existingValue, JsonSerializer serializer)
    {
        // This creates a raw JSON string without parsing it.
        var raw = JRaw.Create(reader);
        var obj = new ObjectJsonWrapper();
        obj.Json = (string)raw.Value;
        return obj;
    }

    public override void WriteJson(JsonWriter writer, object value, 
        JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

To use it:

public class MyObject
{
    public ObjectJsonWrapper LargeObject { get; set; }
}

[JsonConverter(typeof(ObjectJsonWrapperConverter))]
public class ObjectJsonWrapper
{
    public string Json { get; set; }
}

var json = @"
{
  ""largeObject"": {
    ""value"": ""some value""
  }
}   
";

var obj = JsonConvert.DeserializeObject<MyObject>(json);
weichch
  • 9,306
  • 1
  • 13
  • 25