whoacowboy whoacowboy - 21 days ago 14
C# Question

Errors parsing JSON using Newtonsoft.Json

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

Answer

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>();
Comments