web-dev-qa-db-ja.com

Newtonsoft.Jsonを使用したJSONの解析エラー

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; }
}
10
whoacowboy

「flags1」オブジェクトの両方のプロパティには「string」という名前が付いているため、プロパティを2回定義することはできません。

編集:少なくとも最新のnugetバージョンでは、JObject.Parseはエラーをスキップし、データを適切に解析しているようです。私はあなたがあなたのためにそれを機能させることができることを願っています。

これを行う方法の例を次に示します。

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

Connor Hilaridesの回答に加えて、配列を含めて使用できます。

JToken resultToken = JToken.Parse(unfilteredJSONData);
3
quckly