Как я могу десериализовать недопустимый json? Усеченный список объектов

#c# #json #json.net

#json #json.net

Вопрос:

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

 [ { "key" : "value1" }, { "key " : "value2"}, { "key 
  

Пожалуйста, скажите мне, есть ли способ с помощью Newtonsoft.Библиотека Json, или мне нужна некоторая предварительная обработка.

Спасибо!

Комментарии:

1. JSON — это не HTML, нет веской причины расширять библиотеки, реализующие обходные пути для недопустимых данных. Вероятно, вы используете компьютерный язык для обработки JSON; не должно быть сложно реализовать предварительную обработку с помощью функций обработки строк из такого языка (C #?).

Ответ №1:

Выглядит как на Json.NET 8.0.3 вы можете передавать свою строку из JsonTextReader в JTokenWriter a и получать частичный результат, перехватывая и проглатывая JsonReaderException то, что выдается при разборе усеченного JSON:

 JToken root;
string exceptionPath = null;
using (var textReader = new StringReader(badJson))
using (var jsonReader = new JsonTextReader(textReader))
using (JTokenWriter jsonWriter = new JTokenWriter())
{
    try
    {
        jsonWriter.WriteToken(jsonReader);
    }
    catch (JsonReaderException ex)
    {
        exceptionPath = ex.Path;
        Debug.WriteLine(ex);
    }
    root = jsonWriter.Token;
}

Console.WriteLine(root);
if (exceptionPath != null)
{
    Console.WriteLine("Error occurred with token: ");
    var badToken = root.SelectToken(exceptionPath);
    Console.WriteLine(badToken);
}
  

Это приводит к:

 [
  {
    "key": "value1"
  },
  {
    "key ": "value2"
  },
  {}
]
  

Затем вы могли бы завершить десериализацию частичного объекта с помощью JToken.ToObject . Вы также можете удалить запись неполного массива с помощью badToken.Remove() .

Было бы лучше вообще не генерировать недопустимый JSON. Я также не совсем уверен, что это документированная функциональность Json.NET и, следовательно, он может не работать с будущими версиями Json.NET . (Например, возможно, Newtonsoft может изменить свой алгоритм таким образом, что JTokenWriter.Token устанавливается только при успешной записи.)

Ответ №2:

Вы можете использовать класс JsonReader и попытаться проанализировать, насколько это возможно. Что-то вроде приведенного ниже кода проанализирует столько свойств, сколько получит, а затем выдаст исключение. Это, конечно, если вы хотите десериализовать в конкретный класс.

 public Partial FromJson(JsonReader reader)
{
    while (reader.Read())
    {
        // Break on EndObject
        if (reader.TokenType == JsonToken.EndObject)
            break;

        // Only look for properties
        if (reader.TokenType != JsonToken.PropertyName)
            continue;

        switch ((string) reader.Value)
        {
            case "Id":
                reader.Read();
                Id = Convert.ToInt16(reader.Value);
                break;

            case "Name":
                reader.Read();
                Name = Convert.ToString(reader.Value);
                break;

        }
    }

    return this;
}
  

Код взят из целевого объекта CGbR JSON.

Ответ №3:

второй ответ выше действительно хорош и прост, помог мне!

         static string FixPartialJson(string badJson)
        {
            JToken root;
            string exceptionPath = null;
            using (var textReader = new StringReader(badJson))
            using (var jsonReader = new JsonTextReader(textReader))
            using (JTokenWriter jsonWriter = new JTokenWriter())
            {
                try
                {
                    jsonWriter.WriteToken(jsonReader);
                }
                catch (JsonReaderException ex)
                {
                    exceptionPath = ex.Path;                    
                }
                root = jsonWriter.Token;
            }

            return root.ToString();            
        }