使用 Newtonsoft.Json 解析 JSON 时出错

Posted

技术标签:

【中文标题】使用 Newtonsoft.Json 解析 JSON 时出错【英文标题】:Errors parsing JSON using Newtonsoft.Json 【发布时间】:2012-12-17 09:35:04 【问题描述】:

当我尝试使用 Newtonsoft.Json 解析我的 JSON 时遇到以下错误

Response result = JsonConvert.DeserializeObject<Response>(unfilteredJSONData);

无法将属性字符串添加到 Newtonsoft.Json.Linq.JObject。对象上已存在同名属性。

我无法控制 JSON 提要,他们只是添加了 flags1flags2。重复的字符串似乎导致了错误,但我对如何解决它没有任何好主意。在添加新字段之前,此代码运行良好。

更新:


第一个错误是由使用过时的 JSON.net 版本引起的。我正在使用的 CMS 系统有一个内置版本,它是 3.5。当我使用 4.5 时,我收到一个新错误:

无法将 Newtonsoft.Json.Linq.JValue 添加到 Newtonsoft.Json.Linq.JObject。

事实证明,我下面的 JSON 格式与我正在处理的格式不完全相同。请注意更新。错误似乎是在这里引起的:

"flags1": 
    "string": "text",
    "string": "text"
,

JSON 是:


    "result":
    
        "lookups":
        [
            
                "groups":
                [
                    
                        "item0": "text",
                        "item1": "text",
                        "item2": 0,
                        "item3": 0,
                        "item4": 11.5,
                        "item5": true
                    ,
                    
                        "item6": "text",
                        "oddName": "text"
                    ,
                    
                        "item7": 
                            "subitem0": "text",
                            "subitem1": 0,
                            "subitem2": true
                        ,
                        "item8": 
                            "subitem0": "string",
                            "subitem1": 0,
                            "subitem2": true
                        
                    ,
                    
                        "url": "http://google.com",
                        "otherurl": "http://yahoo.com",
                        "alturllist": [],
                        "altotherurl": []
                    ,
                    ,
                    
                        "flags1": 
                            "string": "text"
                        ,
                        "flags2": 
                            "string": "text"
                        
                    
                ]
            ,
            
                "groups":
                [
                    
                        "item0": "text",
                        "item1": "text",
                        "item2": 0,
                        "item3": 0,
                        "item4": 11.5,
                        "item5": true
                    ,
                    
                        "item6": "text",
                        "oddName": "text"
                    ,
                    
                        "item7": 
                            "subitem0": "text",
                            "subitem1": 0,
                            "subitem2": true
                        ,
                        "item8": 
                            "subitem0": "string",
                            "subitem1": 0,
                            "subitem2": true
                        
                    ,
                    
                        "url": "http://google.com",
                        "otherurl": "http://yahoo.com",
                        "alturllist": [],
                        "altotherurl": []
                    ,
                    ,
                    
                        "flags1": 
                            "string": "text",
                            "string": "text"
                        ,
                        "flags2": 
                    
                ]
            
        ]
    

C# 类是:

// response
[DataContract]
public class Response

    [DataMember(Name = "result")]
    public Result result  get; set; 

[DataContract]
public class Result

    [DataMember(Name = "lookups")]
    public List<Item> lookups  get; set; 

[DataContract]
public class Item

    [DataMember(Name = "groups")]
    public List<Dictionary<string, object>> groups  get; set; 

为了清楚起见,我简化了 JSON 和代码示例。

我包含了代码 aspx 以简化复制。

test.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Test.aspx.cs" Inherits="Test" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    <code>
    <%=response %>
    </code></div>
    </form>
</body>
</html>

test.aspx.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Runtime.Serialization;

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

using NLog;

public partial class Test : System.Web.UI.Page

    public string response = string.Empty;
    public static string cacheDirPath = HttpRuntime.AppDomainAppPath + "cache\\";
    private static Logger log = LogManager.GetLogger("productFeed");

    protected void Page_Load(object sender, EventArgs e)
    

        response = readDataFromFile(cacheDirPath + "test2.json");
        Response masheryResult = JsonConvert.DeserializeObject<Response>(response);
    
    private string readDataFromFile(string filePath)
    
        string JSONData = string.Empty;
        try
        
            StreamReader myFile = new StreamReader(filePath);

            JSONData = myFile.ReadToEnd();

            myFile.Close();
        
        catch (Exception e)
        
            log.Warn(e.Message);
        

        return JSONData;
    


// response
[DataContract]
public class Response

    [DataMember(Name = "result")]
    public Result result  get; set; 

[DataContract]
public class Result

    [DataMember(Name = "lookups")]
    public List<Item> lookups  get; set; 

[DataContract]
public class Item

    [DataMember(Name = "groups")]
    public List<Dictionary<string, object>> groups  get; set; 

【问题讨论】:

您的示例 JSON 没有问题。它反序列化就好了。 对我来说也没有问题。您使用的是什么版本的 Json.NET,我使用的是 nuget 的 4.5.0.0。上面的 json 是您遇到反序列化问题的确切文本,还是只是一个表示形式。 @Robert Slaney - 我使用的是 Ektron CMS 系统中内置的 dll。 3.5 版,当我使用 nuget 4.5 版时,错误消失了。出现另一个我必须调查的错误。 '不能将 Newtonsoft.Json.Linq.JValue 添加到 Newtonsoft.Json.Linq.JObject。'不幸的是,这不是确切的代码,我正在处理的是更加不守规矩的。谢谢。 【参考方案1】:

“flags1”对象中的两个属性都被命名为“string”,你不能重复定义一个属性。

编辑:看来,至少在最新的 nuget 版本中,JObject.Parse 跳过了错误并正确解析了数据!我希望你能做到这一点。

下面是一个示例:

Response result = JObject.Parse(unfilteredJSONData).ToObject<Response>();

【讨论】:

感谢您的回复,但我无法控制 JSON。有没有偶然的解决方法? 有谁知道为什么这有效而 JsonConvert 无效?这种方法的优缺点是什么? 我认为这种方法是有效的,因为 JObject 动态构建树,而 JsonConvert 试图有效地做到这一点并抱怨数据不好。 JsonConvert 肯定更快,您应该尽可能使用它,但在这种情况下,JObject 是最好的解决方案。【参考方案2】:

除了Connor Hilarides 答案,它还可以用于包括数组:

JToken resultToken = JToken.Parse(unfilteredJSONData);

【讨论】:

以上是关于使用 Newtonsoft.Json 解析 JSON 时出错的主要内容,如果未能解决你的问题,请参考以下文章

C#解析JSON字符串总结

“Newtonsoft.Json.JsonConvert”类型存在于“Newtonsoft.Json.dll”和“NuGetApi2.dll”中

比Newtonsoft.Json轻量快速简洁的实体JSON转换库YeaJur.Mapper

如何使用 Newtonsoft.JSON 解析 JSON 响应? [复制]

Newtonsoft.Json解析数组

C# unity (发布到安卓端中使用)解析json字符串—使用微软官方的包Newtonsoft.Json