16

I am getting the following error when I try and parse my JSON using Newtonsoft.Json using

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

Can not add property string to Newtonsoft.Json.Linq.JObject. Property with the same name already exists on object.

I have no control over the JSON feed and they just added flags1 and flags2. The duplicate string seems to be causing the error, but I don't have any good idea on how to resolve it. This code was working well until the addition of the new fields.

Update:


The first error was caused by using an outdated version of JSON.net. There was a built-in version with the CMS system I am using and it was 3.5. When I use 4.5 I get a new error:

Can not add Newtonsoft.Json.Linq.JValue to Newtonsoft.Json.Linq.JObject.

It turns out my JSON below was not exactly the same format as what I am dealing with. Please note the update. The error seems to be caused here:

"flags1": {
    "string": "text",
    "string": "text"
},

The JSON is:

{
    "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": {}
                    }
                ]
            }
        ]
    }
}

The C# classes are:

// 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; }
}

I have simplified the JSON and code example for clarity.

I included the code aspx to simplify reproducing.

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; }
}
3
  • No problems here with your example JSON. It deserializes just fine. Commented Jan 3, 2013 at 4:38
  • 1
    No issues for me as well. What version of Json.NET are you using, i'm using 4.5.0.0 from nuget. Is the above json the exact text you have deserialisation problem with, or just a representation. Commented Jan 3, 2013 at 6:55
  • @Robert Slaney - I was using the dll built into the Ektron's CMS system. Version 3.5, when I used the nuget version 4.5 the error goes away. Another error appears which I have to look into. 'Can not add Newtonsoft.Json.Linq.JValue to Newtonsoft.Json.Linq.JObject.' This isn't the exact code unfortunately what I am dealing with is much more unruly. Thank you. Commented Jan 3, 2013 at 19:40

2 Answers 2

23

Both the properties in the "flags1" object are named "string", you can't define a property twice.

Edit: It seems that, at least in the latest nuget version, JObject.Parse skips over the error and properly parses the data! I hope you can make that work for you.

Here's an example of how you can do it:

Response result = JObject.Parse(unfilteredJSONData).ToObject<Response>();
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the response, but I have no control over the JSON. Is there a work around by chance?
Does anyone know why this works and JsonConvert does not? What are the pros/cons of this approach?
I think this approach works because JObject builds the tree dynamically, and JsonConvert tries to do it efficiently and complains with bad data. JsonConvert is definitely faster, and you should use it whenever it's possible, but in a case like this JObject is the best solution.
3

In additional to Connor Hilarides answer, it can be used including arrays:

JToken resultToken = JToken.Parse(unfilteredJSONData);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.