Bercovici Adrian
Bercovici Adrian

Reputation: 9360

How to deserialize JSON with dependant properties?

I was wondering if I have an object that contains a field which has its deserialization process dependant on another field, how can I deserialize the parent object?

Container

class Container
{ 
    public int Id { get; set; }
    public object Data { get; set; } //deserialization depends on first field
}

Hierarchy

class FieldType1
{
    public string Value { get; set; }
}

class FieldType2
{
    public int Numbers { get; set; }
}

Given the example above if I have a Dictionary<int,Type> how can I deserialize an object that comes as a string like the one below?:

var container = new Container { Data = new FieldType1 { Value = "sata" }};
var str = JsonConvert.SerializeObject(container);
var clone = JsonConvert.DeserializeObject<Container>(str);//has dependant field on another field

As you can see in my example above I always have the same container type.but one property differs.

Update

After some answers here could it be possible to keep only one type of parent object and instead have a base type for the second field ?

  [JsonSubTypes.KnownSubType(typeof(Child1),1)]
  [JsonSubTypes.KnownSubType(typeof(Child2),2)]
  public abstract Child
  {
  }


 public class Parent{
 public int Id;
 public Child child;

 }

Can i decorate somehow the parent to know how to deserialize its second field (similar to JsonSubTypes)?


Summing it up i do not want to have P,P1,P2..Pn types for parent. I want to have one type P for parent with F1,F2...Fn types for its second field.So that when i deserialize i would just say JsonConvert.DeserializeObject<P> while the converter takes care of which concrete type is the second field:

 Parent c1=new P{ id=1,child=new Child1()};
 Parent c2=new P{ id=2,child=newChild2()};
 List<Parent> items=new List<Parent>{c1,c2};
 var str=JsonConvert.SerializeObject(items);

 var clone=JsonConvert.DeserializeObject<List<Parent>>(str);

Upvotes: 3

Views: 1140

Answers (1)

Ralph Willgoss
Ralph Willgoss

Reputation: 12163

At a first glance, I'd simply use a simple function that you could put into a SomeNameParser/Converter class.

Pesudo C# code, something like the following:

var jObject = JObject.Parse(obj.Data);
switch (jObject["firstField"])
{
   case "fieldType1":
     return JsonConvert.DeserializeObject<string>(str);

   case "fieldType2":
     return JsonConvert.DeserializeObject<int>(str);

   default:
     Throw new Exception( make this meaningful)
}

Improvements
You could make the parsing of the firstField do a lookup to return a System.Type, then pass the type to JsonConvert.Deserialize(obj.Data, type) which would save the repetitive JsonConvert.

Hopefully you can see the general pattern.

Upvotes: 2

Related Questions