Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deserialize derived classes using Json.net without using JObject

Tags:

json

c#

json.net

I have a large json dataset that I need to deserialize. I am using Json.net's JsonTextReader to read the data.

My problem is that I need to deserialize some derived classes, so I need to be able to "look ahead" for a particular property defining my data type. In the example below, the "type" parameter is used to determine the object type to deserialize.

{
  type: "groupData",
  groupParam: "groupValue1",
  nestedObject: 
  {
    type: "groupData",
    groupParam: "groupValue2",
    nestedObject:
    {
      type: "bigData",
      arrayData: [ ... ]
    }
  }

My derived objects can be heavily nested and very deep. Loading the entire dataset in memory is not desired since it will require much memory. Once I get down to the "bigData" object, I will be processing the data (such as the array in the example above), but it will not be stored in memory (it is too big).

All solutions to my problem that I have seen so far have utilized JObject to deserialize the partial objects. I want to avoid using JObject because it will deserialize every object down the hierarchy repeatedly.

How can I solve my deserialization issue?

Is there any way to search ahead for the "type" parameter, then backtrack to the start of the object's { character to start processing?

like image 850
Matt Houser Avatar asked May 15 '13 01:05

Matt Houser


1 Answers

I not aware of anyway to prempt the loading in of the object in order to specify a lookahead (at least not in Json.NET) but you could use the other attribute based configuration items at your disposal in order to ignore unwanted properties:

public class GroupData {
    [JsonIgnore]
    public string groupParam { get; set; }
    [JsonIgnore]
    public GroupData nestedObject { get; set; }

    public string[] arrayData { get; set; }
}

Alternatively, you can give custom creation converters a try:

For example..

public class GroupData {
    [JsonIgnore]
    public string groupParam { get; set; }
    [JsonIgnore]
    public GroupData nestedObject { get; set; }
}

public class BigData : GroupData {
    public string[] arrayData { get; set; }
}

public class ObjectConverter<T> : CustomCreationConverter<T>
{
    public ObjectConverter() { }

    public override bool CanConvert(Type objectType)
    {
        return objectType.Name == "BigData";
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        // Some additional checks/work?
       serializer.Populate(reader, target);
    }
}
like image 125
Stumblor Avatar answered Oct 12 '22 20:10

Stumblor