Как настроить десериализацию вложенного свойства в Json. net без добавления атрибутов - PullRequest
0 голосов
/ 09 марта 2020

Предположим, у меня есть эти классы:

public class Bar
{
    public Foo MyFoo { get; set; }
}

public class Foo
{
    public string[] Stuff { get; set; }
}

И у меня есть такая структура JSON:

{
  "MyFoo":
  {
    "Stuff":"those,are,my,stuff"
  }
}

И у меня есть путь к коду, в который преобразуется JObject Bar используя код, подобный приведенному ниже:

myJObject.ToObject(typeof(Bar))

Теперь мне нужно предоставить ToObject специальный сериализатор для преобразования строкового свойства Stuff в массив строк (используя string.Split(...).ToArray())

Меня попросили не добавлять атрибуты в клиентский класс 'Bar', поэтому после просмотра мне показалось, что ContractResolver в порядке, но проблема в том, что распознаватель позволяет мне обрабатывать только прямые свойства типа root, то есть Bar в моем примере, и я не могу зарегистрировать JsonConverter для вложенного свойства.

Так что мой вопрос к вам, ребята, является ли это достижимым? используя Json. net?

  • Обратите внимание, что мне нужно сделать это не только для класса Bar, но и для неограниченного количества классов с неизвестной структурой, поэтому я не могу жестко написать решение, которое будет работать для одного типа класса.

1 Ответ

0 голосов
/ 10 марта 2020

Исходя из вашего описания, я не понимаю, почему вам понадобится ContractResolver. Вы знаете, что свойства, которые вы хотите специально десериализовать, всегда будут иметь тип string[], поэтому просто создайте конвертер, который обрабатывает этот тип. Может быть что-то вроде этого:

public class CsvStringConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(string[]);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JToken token = JToken.Load(reader);

        if (token.Type == JTokenType.Null) 
            return null;

        if (token.Type == JTokenType.String)
            return ((string)token).Split(',');

        if (token.Type == JTokenType.Array) 
            return token.ToObject<string[]>(serializer);

        throw new JsonException("Unexpected token type: " + token.Type);
    }

    public override bool CanWrite => false;

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

Затем, чтобы использовать его с вашим JObject, создать новый экземпляр JsonSerializer, добавить к нему конвертер и передать сериализатор в метод ToObject(), например: это:

var serializer = new JsonSerializer();
serializer.Converters.Add(new CsvStringConverter());

var bar = myJObject.ToObject<Bar>(serializer);

Рабочая демонстрация здесь: https://dotnetfiddle.net/qmeBoh

...