-2

I have an issue where an API i am trying to consume in .NET is using numeric keys. I have provided a sample of the JSON below.

{
"com": {
            "categories": [
                "gTLD",
                "Popular"
            ],
            "addons": {
                "dns": true,
                "email": true,
                "idprotect": true
            },
            "group": "hot",
            "register": {
                "1": "11.99",
                "2": "23.98",
                "3": "35.97",
                "4": "47.96",
                "5": "59.95",
                "6": "71.94",
                "7": "83.93",
                "8": "95.92",
                "9": "107.91",
                "10": "119.90"
            },
            "transfer": {
                "1": "11.99",
                "2": "23.98",
                "3": "35.97",
                "4": "47.96",
                "5": "59.95",
                "6": "71.94",
                "7": "83.93",
                "8": "95.92",
                "9": "107.91",
                "10": "119.90"
            },
            "renew": {
                "1": "11.99",
                "2": "23.98",
                "3": "35.97",
                "4": "47.96",
                "5": "59.95",
                "6": "71.94",
                "7": "83.93",
                "8": "95.92",
                "9": "107.91",
                "10": "119.90"
            },
            "grace_period": {
                "days": 30,
                "price": "£0.00"
            },
            "redemption_period": null
        }
    }

I am trying to extract the register prices out of the JSON in Razor to use in a table, however i just can't seem to access the values.

The Razor code:

var client = new RestClient("JSON_URL");
IRestResponse response = client.Execute(new RestRequest());
var o = JObject.Parse(response.Content);

@foreach (JProperty child in o["pricing"])
{
    <strong>@child.Name</strong>
    foreach (JObject ext in child.Children())
    {
        foreach (var property in ext["register"].Select(f => f.ToObject<GetDomainPricing>()))
        {
            @property
        }
    }
}

And the associated Model:

namespace TH.Models
{
    public class GetDomainPricing
    {
        public string Price { get; set; }
    }
}

After a week of battling with this error, the message i have ended up on is:

Newtonsoft.Json.JsonSerializationException: Unexpected token while deserializing object: PropertyName. Path 'pricing.com.register.1', line 1, position 243.

So at this point i am in need of some help, i don't have access to the JSON to change its format, but a link to the documentation is below: GetTldPricing - WHMCS Developer Documentation

All their examples are using PHP which looks like it doesn't have this issue.


Solution

For anyone else trying to work out how to parse dynamic JSON with numeric keys, my answer is below.

Model:

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

namespace TerrabitHost.Models
{
    public class Addons
    {
        public bool dns { get; set; }
        public bool email { get; set; }
        public bool idprotect { get; set; }
    }

    public class GracePeriod
    {
        public int days { get; set; }
        public string price { get; set; }
    }

    public class Pricing
    {
        public Extensions Tld { get; set; }
    }
    public class Extensions
public class Extensions
{
    public List<string> categories { get; set; }
    public Addons addons { get; set; }
    public string group { get; set; }
    public Prices register { get; set; }
    public Prices transfer { get; set; }
    public Prices renew { get; set; }
    public GracePeriod grace_period { get; set; }
    public object redemption_period { get; set; }
}

    public class Register
    {
        [JsonProperty(PropertyName = "1")]
        public string One { get; set; }
        [JsonProperty(PropertyName = "2")]
        public string Two { get; set; }
        [JsonProperty(PropertyName = "3")]
        public string Three { get; set; }
    }

    public class GetDomainPricing
    {
        public Pricing[] Pricing { get; set; }
    }
    public class JsonBody
    {
        public Dictionary<string, Extensions> Pricing { get; set; }
    }
}

Razor View:

@{
    var client = new RestClient("JSON_URL");
    IRestResponse response = client.Execute(new RestRequest());
    JsonBody json = JsonConvert.DeserializeObject<JsonBody>(response.Content);
}

@foreach (var ext in json.Pricing)
{
<strong>@ext.Key</strong>
@ext.Value.register.One);
}
Community
  • 1
  • 1
Aaron
  • 19
  • 4

2 Answers2

2

The easiest way to deal with these is to deserialise them as Dictionary<int, string>. For example, using the following classes:

public class Addons
{
    public bool dns { get; set; }
    public bool email { get; set; }
    public bool idprotect { get; set; }
}

public class GracePeriod
{
    public int days { get; set; }
    public string price { get; set; }
}

public class Com
{
    public List<string> categories { get; set; }
    public Addons addons { get; set; }
    public string group { get; set; }
    public Dictionary<int, string> register { get; set; }
    public Dictionary<int, string> transfer { get; set; }
    public Dictionary<int, string> renew { get; set; }
    public GracePeriod grace_period { get; set; }
    public object redemption_period { get; set; }
}

public class RootObject
{
    public Com com { get; set; }
}

You can now deserialise with this code:

var result = JsonConvert.DeserializeObject<RootObject>(json);
DavidG
  • 113,891
  • 12
  • 217
  • 223
  • I'll post up my answer shortly, but i combined this with bzier's answer and made it dynamic – Aaron Jun 17 '18 at 22:01
0

Take a look at the question/answer here: Deserialize json that has some property name starting with a number

You will likely need to deserialize the JSON into an instance of a class you define. You can map the property names from the JSON to valid C# property names.

Borrowing/adapting the example from the referenced answer (credit to Borys Generalov),

   public class MyClass
   {
        [JsonProperty(PropertyName = "1")]
        public string One { get; set; }

        [JsonProperty(PropertyName = "2")]
        public string Two { get; set; }
        ...

Now to deserialize:

    string jsonData = ...    
    MyClass deserializedMyClass = JsonConvert.DeserializeObject<MyClass>(jsonData);
bzier
  • 445
  • 3
  • 11