JoshG
JoshG

Reputation: 6745

How to parse a complicated nested JSON string in C#?

I have an ugly JSON string that is getting returned from an API that looks like this (this is the result of Console.Write on the string):

{"d":"\"\\\"\\\\\\\"[{\\\\\\\\\\\\\\\"foo\\\\\\\\\\\\\\\":15,\\\\\\\\\\\\\\\"bar\\\\\\\\\\\\\\\":null}]\\\\\\\"\\\"\\n\""}

I am trying to parse this into a C# object in the simplest way possible, so I can access properties like foo and bar. But I am having a difficult time doing this.

I have tried parsing it a number of ways, including:

// code to get the response string
client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
var serializedData = "{data: 'data'}";
var responseString = client.UploadString(url, "POST", serializedData);

// parse the response string
dynamic obj = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonString);

This allows me to access the value of d, which is the actual string I need to parse. I then tried to parse that separately using JArray.Parse(obj["d"]), but I get an error saying that obj["d"] is not an array.

Unfortunately, I have no access to the API itself so can't modify how it's serializing the data it's returning.

Any suggestions?

Upvotes: 2

Views: 1098

Answers (3)

Cueball 6118
Cueball 6118

Reputation: 547

Replacing escape characters in fine however I would not rely on the console.write command as the definitive output to examine. Here are a couple of other ways: -

  1. Use Postman to make the API call so you can see the raw result. This will (hopefully) show it in an easy to read format that you can then define your class to deserialise to.
  2. Write the raw response to a “.json” file. Open that file in a good editor (such as VS Code or VS itself) to see how the data is actually structured when it is received.

On a side note I would recommend using RestSharp to do the REST calls and Newtonsoft.Json to do the serialising/deserialising.

Upvotes: 0

Grx70
Grx70

Reputation: 10359

The problem is that the value of "d" is a string representing a string representing a string ... representing an array. You could call it JSON serialization "inception".

The way to deal with this is to deserialize the value corresponding number of times. If you're sure that the value is never going to be an actual string, you could do it like this, without having to know how many times the value was serialized:

var myObject = JObject.Parse(s);
var d = myObject["d"];
while(d.Type == JTokenType.String)
    d = JToken.Parse(d.ToObject<string>());
myObject["d"] = d;

After this procedure myObject represents this data:

{
  "d": [
    {
      "foo": 15,
      "bar": null
    }
  ]
}

Upvotes: 2

Krishna Varma
Krishna Varma

Reputation: 4260

You can replace all New Line, Backslash, Double quotes to format the JSON

var formattedJson =  jsonString.Replace(@"\n", string.Empty)
                               .Replace(@"\", string.Empty)
                               .Replace("\"\"", string.Empty);
Console.WriteLine(formattedJson);

OUTPUT

{
    "d": [
        {
            "foo": 15,
            "bar": null
        }
    ]
}

Convert to JArray.

var jArray = JArray.Parse(JObject.Parse(formattedJson)["d"].ToString());
Console.WriteLine($"{jArray[0]["foo"]} {jArray[0]["bar"]}");

OUTPUT

15

Upvotes: 3

Related Questions