Как интерпретировать и десериализовать этот ответ json

Этот вопрос исходит из другой темы, которую можно найти по адресу: Извлечь объекты из массива JSON в список

Дело в том, что я получаю следующий ответ JSON, и мой десериализатор JSON.NET его не понимает, но несколько других валидаторов JSON, таких как https://jsonlint.com, говорят, что он действителен.

[
{"value":"{\"code\":\"MO\",\"description\":\"Monday\",\"isSet\":false}","nr":1}
,{"value":"{\"code\":\"TU\",\"description\":\"Tuesday\",\"isSet\":true}","nr":2}
]

На мой взгляд, проблема здесь в том, что объект значения выглядит как объект JSON, но на самом деле является строкой. JsonConvert.DeserializeObject продолжает выдавать ошибки, пока я не удалю дополнительные кавычки (") и экранирующие символы.

Возникает вопрос, почему этот ответ имеет такой формат? А как подсказать десериализатору, как с ним работать? Я уверен, что удаление или замена символов - это не лучший вариант.

Вот что я делаю:

public class Value
{
    public string code { get; set; }
    public string description { get; set; }
    public bool isSet { get; set; }
}

public class RootObject
{
    public Value value { get; set; }
    public int nr { get; set; }
}

var json = JsonConvert.DeserializeObject<List<RootObject>>(serviceResult);

Вышеуказанное не работает.

Пока я решил вопрос таким образом. Но я продолжаю думать, что приведенное выше, с десериализатором, более элегантно.

JArray jArray = JArray.Parse(serviceResult);
List<Value> values = jArray.Select(x => JObject.Parse(x["value"].ToString()).ToObject<Value>()).ToList();

Можете ли вы опубликовать код десериализации?

Tadija Bagarić 11.04.2018 11:54

похоже, что он вложен. сами значения являются атрибутами в стиле json, и они закодированы с помощью экранированных кавычек, чтобы соответствовать требованиям для строки.

Cee McSharpface 11.04.2018 11:54

Мне кажется, что это действительный JSON, для чего вы пытаетесь десериализовать его? Связанный вами вопрос неверен.

DavidG 11.04.2018 11:54

Я добавил свой текущий код.

Tys 11.04.2018 12:07

@DavidG, почему этот вопрос неверен?

Tys 11.04.2018 12:09

Просто для справки, я также добавил свое текущее исправление / обходной путь.

Tys 11.04.2018 12:34
0
6
115
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Самый простой способ сделать это - использовать собственный JsonConverter, например что-то вроде этого:

public class StringToObjectConverter<T> : Newtonsoft.Json.JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, 
        JsonSerializer serializer)
    {
        //This will only be needed if you also need to serlialise
        writer.WriteRaw(JsonConvert.SerializeObject(value));
    }

    public override object ReadJson(JsonReader reader, Type objectType, 
        object existingValue, JsonSerializer serializer)
    {
        return JsonConvert.DeserializeObject<T>(reader.Value.ToString());
    }

    public override bool CanRead => true;
    //We can only work with the type T, you could expand this to cope with derived types
    public override bool CanConvert(Type objectType) => typeof(T) == objectType;
}

Теперь, используя эти модели, отметив, в частности, атрибут свойства Value:

public class RootObject
{
    [JsonConverter(typeof(StringToObjectConverter<Value>))]
    public Value value { get; set; }
    public int nr { get; set; }
}

public class Value
{
    public string code { get; set; }
    public string description { get; set; }
    public bool isSet { get; set; }
}

Теперь это простая десериализация:

var json = "....";
var rootObjects = JsonConvert.DeserializeObject<List<RootObject>>(json);

Верно. Это выглядит совершенно понятно. Спасибо. Но затем я продолжаю думать, если это действительный JSON для всех видов инструментов, почему он не поддерживает OOTB наиболее используемой библиотекой JSON.NET?

Tys 11.04.2018 12:26

Ну это просто дополнительная сложность, которая, честно говоря, не нужна. Каждый раз, когда Джеймс Ньютон (парень, который пишет JSON.Net) добавляет еще одну проверку, это замедляет синтаксический анализ для всех.

DavidG 11.04.2018 12:28

Правда. Есть идеи, в чем может быть причина, по которой разработчики сервиса добавили эту дополнительную сложность?

Tys 11.04.2018 12:34

Э, кто знает! Лучше спросить у них. Скорее всего, они используют другую библиотеку, которая работает по-другому. Обратите внимание, что в спецификации JSON не сказано, что строки следует преобразовывать в объекты. Представьте, что у вас есть строка, которая случайно выглядит как JSON, я бы не хотел, чтобы мой синтаксический анализатор делал с ней что-нибудь умное.

DavidG 11.04.2018 12:38

Я думаю, вам нужно вызвать WriteRaw() внутри WriteValue(), а не WriteJson().

dbc 11.04.2018 19:39

@dbc Да, возможно, вы правы, я не тестировал сериализацию.

DavidG 12.04.2018 00:38

Другие вопросы по теме