我的json文件主要是一个包含对象的数组,但列表不完整,所以我不能使用最后一个条目。我想在丢弃最后一个无效条目时反序列化文件的其余部分
[ { "key" : "value1" }, { "key " : "value2"}, { "key
请告诉我是否有使用Newtonsoft.Json库的方法,或者我是否需要进行一些预处理。
谢谢!
答案 0 :(得分:5)
在Json.NET 8.0.3上看起来,您可以将字符串从JsonTextReader
流式传输到JTokenWriter
,并通过捕获和吞下被引发的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
。)
答案 1 :(得分: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 Target。
答案 2 :(得分:0)
上面的第二个答案真的很好,很简单,帮了我忙!
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();
}