Skundlony
Skundlony

Reputation: 61

How to deserialize JSON to IList<KeyValuePair<string, object>> with whitespaces in key?

I have a big problem with deserializing my JSON to an object. It should be deserialized to IList<KeyValuePair<string, object>> the problem is that the keys have white spaces.

"spec": {
         "SOMETHING WITH SPACES" : "10"
         etc. 
         ...
}
public class SomeObject
{
...
public IList<KeyValuePair<string, object>> spec{ get; set; }
...
}

Deserializing code:

var sr = new ServiceStack.Text.JsonSerializer<SomeObject>();
var esResult = sr.DeserializeFromString(responseJson);

responseJson is a GET from ElasticSearch.

What I get to my field it is null. If I have key without whitespaces it's deserializing normally and I'm getting my IList<KeyValuePair<string, object>>

Upvotes: 1

Views: 2088

Answers (3)

Peter B
Peter B

Reputation: 24136

You can't use IList or List here, because your source JSON has no [ ] in it, which is a requirement if you want to parse into such a collection. In other words, without [ ] you can't parse into a collection, at least not without going through lots of hoops.

Instead you need to use a Dictionary as was suggested already in comments.

Note: I used Newtonsoft JsonConvert because you didn't state what your parser is, but that should make little or no difference to my arguments.

Working code:

var json = "{ \"spec\": { \"SOMETHING WITH SPACES\" : \"10\" } }";
var someObj = JsonConvert.DeserializeObject<SomeObject>(json);

public class SomeObject
{
    public Dictionary<string, object> spec{ get; set; }
}

After that, you can cast the spec property to an IEnumerable and loop through whatever was found:

foreach (var pair in someObj.spec as IEnumerable<KeyValuePair<string, object>>)
{
    Console.WriteLine(pair.Key + " -> " + pair.Value);
}

Or even convert it to a List:

var list = someObj.spec.ToList();
foreach (var pair in list)
{
    Console.WriteLine(pair.Key + " -> " + pair.Value);
}

.NET Fiddle: https://dotnetfiddle.net/15l2R3

Upvotes: 2

Malior
Malior

Reputation: 1341

I guess your JSON serialiazer makes some trouble. I'd recommend to use Newtonsoft.Json (in NuGet) I've tried following code, and it works fine:

        var o1 = new SomeObject() { spec = new List<KeyValuePair<string, object>>() };
        o1.spec.Add(new KeyValuePair<string, object>("test with spaces", 10));

        var r1 = Newtonsoft.Json.JsonConvert.SerializeObject(o1);
        Console.WriteLine(r1);
        var o2 = Newtonsoft.Json.JsonConvert.DeserializeObject<SomeObject>(r1);
        var r2 = Newtonsoft.Json.JsonConvert.SerializeObject(o2);
        Console.WriteLine(r2);

The outcome is

{"spec":[{"Key":"test with spaces","Value":10}]}
{"spec":[{"Key":"test with spaces","Value":10}]}

No null values, all works fine.

EDIT: I actually see no reason, why spaces should be any problem at all. They are just part of the string.

Upvotes: 0

Bart van der Drift
Bart van der Drift

Reputation: 1336

If you don't mind using Newtonsoft.Json:

    const string json = @"{""spec"": { ""SOMETHING WITH SPACES"" : ""10"", ""SOMETHING WITH MORE SPACES"" : ""20"" }}";
    dynamic data = JsonConvert.DeserializeObject(json);
    Dictionary<string, string> list = data["spec"].ToObject<Dictionary<string, string>>();
    foreach (var item in list)
    {
        Console.WriteLine(item.Key + ", " + item.Value);
    }

Upvotes: 0

Related Questions