Lincoln King-Cliby
Lincoln King-Cliby

Reputation: 3

C# JSON deserialize same object that acts like an array without being an array

I feel like I'm making this much harder than it needs to be.

In C# using Netwonsoft JSON Compact with external data. Trying to figure out how to deserialize/parse data that looks like

{"http":{"0":{"title":"arbitrary","value":"arbitrary"},"1":{"title":"arbitrary","value":"arbitrary"}},"sip":{"1003":{"title":"arbitrary","value":"none"}}}

It's essentially an array of notifications and the ID -- "0", "1", and "1003" in the above examples is an arbitrary value and appears to have a valid range of 0 and roughly 65535.

But it's not formatted as an array (or I wouldn't be here) -- need help figuring out how to deserialize the value object while essentially ignoring the string identifier.

Thanks in advance

Upvotes: 0

Views: 309

Answers (2)

Luis Lavieri
Luis Lavieri

Reputation: 4129

If you can't change the structure of the JSON, you can always do something like this. The dynamic type figures out what to do on runtime.

dynamic d = JsonConvert.DeserializeObject("{'http':{'0':{'title':'arbitrary','value':'arbitrary'},'1':{'title':'arbitrary','value':'arbitrary'}},'sip':{'1003':{'title':'arbitrary','value':'none'}}}");

Console.WriteLine(d.http["0"].title); // arbitrary

foreach(var prop in d.http) {
  Console.WriteLine(prop);   
}

foreach(var prop in d.sip) {
  Console.WriteLine(prop);   
}

Final output:

arbitrary
"0": {
  "title": "arbitrary",
  "value": "arbitrary"
}
"1": {
  "title": "arbitrary",
  "value": "arbitrary"
}
"1003": {
  "title": "arbitrary",
  "value": "none"
}

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1502985

You can't easily deserialize it as an array, but you can deserialize it to a dictionary with integer keys. I don't know about Json.NET Compact, but this works fine with regular Json.NET:

using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;

class Root
{
    public Dictionary<int, Property> Http { get; set; }
    public Dictionary<int, Property> Sip { get; set; }
}

class Property
{
    public string Title { get; set; }
    public string Value { get; set; }
}

class Test
{
    static void Main()
    {
        string json = File.ReadAllText("test.json");
        var root = JsonConvert.DeserializeObject<Root>(json);
        foreach (var entry in root.Http)
        {
            Console.WriteLine($"{entry.Key}: {entry.Value.Title}/{entry.Value.Value}");
        }
    }
}

If you really need the properties as arrays, I'd suggest having two separate classes: one for the JSON representation, and then another for real usage. For example:

class RootJson
{
    public Dictionary<int, Property> Http { get; set; }
    public Dictionary<int, Property> Sip { get; set; }
}

class Root
{
    // TODO: Control access more :)
    public Property[] Http { get; set; }
    public Property[] Sip { get; set; }
}

Then:

var rootJson = ...;
var root = new Root
{
    Http = rootJson.Http.Values.ToArray(),
    Sip = rootJson.Sip.Values.ToArray(),
};

Upvotes: 1

Related Questions