Как десериализовать JSON с зависимыми свойствами? - PullRequest
0 голосов
/ 01 марта 2019

Мне было интересно, есть ли у меня объект, содержащий поле, процесс десериализации которого зависит от другого поля, как я могу десериализовать родительский объект?

Контейнер

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

Иерархия

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

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

Учитывая приведенный выше пример, если у меня есть Dictionary<int,Type>, как я могу десериализовать объект, который выглядит как строка, подобная приведенной ниже?:

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

Как вы можете видеть в моем примере выше, у меня всегда один и тот же container тип. Но одно свойство отличается.

Обновление

После некоторых ответов здесь можно было бы сохранить только один тип родительского объекта и вместо этого иметь базовый тип для второго поля?

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


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

 }

Могу ли я как-то украсить родительский объект, чтобы знать, как десериализовать его второе поле(похоже на JsonSubTypes)?


Подводя итог, я не хочу иметь P,P1,P2..Pn типов для родителя.Я хочу иметь один тип P для родителя с F1,F2...Fn типами для его второго поля. Чтобы при десериализации я просто сказал JsonConvert.DeserializeObject<P>, а конвертер позаботился о том, какой конкретный тип является вторым полем:

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

1 Ответ

0 голосов
/ 01 марта 2019

На первый взгляд, я бы просто использовал простую функцию, которую можно поместить в SomeNameParser / Converter класс.

Pesudo C # код, что-то вроде следующего:

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

Улучшения Вы можете заставить анализ firstField выполнить поиск, чтобы вернуть System.Type, а затем передать тип в JsonConvert.Deserialize(obj.Data, type), что сохранит повторяющийся JsonConvert.

Надеюсь, вы увидитеобщая схема.

...