#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();
}