如何反序列化无效的json?截断的对象列表

时间:2016-04-12 14:54:37

标签: json json.net

我的json文件主要是一个包含对象的数组,但列表不完整,所以我不能使用最后一个条目。我想在丢弃最后一个无效条目时反序列化文件的其余部分

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

请告诉我是否有使用Newtonsoft.Json库的方法,或者我是否需要进行一些预处理。

谢谢!

3 个答案:

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