简体   繁体   中英

Questioning received JSON structure

I'm currently using a beta API ( http://developer.riotgames.com/api/methods ) which returns JSON for all the exposed methods. I've been able to use JSON.NET to deserialize all of these return values so far. However, today I consumed one of their function which returns a JSON that is valid but is in my opinion not correct.

You're probably wondering, why don't you ask it on the beta forum? I have but I haven't received an answer so far and in general this intrigues me.

A snippet of the JSON return:

    "1001": {
     "name": "Boots of Speed",
     "plaintext": "Slightly increases Movement Speed",
     "group": "BootsNormal",
     "description": "<...
    }

The problem I have with this structure is that the ID is used as a "group" without an identifier. I would be able to use this decently if it had

"ItemID" : "1001"

But it doesn't have that. I don't mind manually parsing it but I'd first like to know whether or not this JSON is correct (not just valid).

Do you agree that this is not a clean way of creating a JSON block that contains a list of elements or am I missing something here? So far I haven't seen any comments on the beta forum of this API so I'm really wondering why.

Edit "valid" vs "correct/usable": I know it's a valid JSON statement. I'm questioning the fact whether this is usable with JSON.NET.

I have the following class definition (with two subclasses):

public class JSONItem
{
    [JsonProperty("tags")]
    public string[] Tags { get; set; }

    [JsonProperty("plaintext")]
    public string Plaintext { get; set; }

    [JsonProperty("description")]
    public string Description { get; set; }

    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonProperty("into")]
    public string[] Into { get; set; }

    [JsonProperty("image")]
    public JSONItemImage Image { get; set; }

    [JsonProperty("colloq")]
    public string Colloq { get; set; }

    [JsonProperty("gold")]
    public JSONItemGold Gold { get; set; }
}

When giving the above JSON block to to JSONConvert.DeserializeObject(json) it throws an error because "1001" is not mentioned in JSONItem. How do you handle this so that you can use JSON.NET?

A class like this won't work because you have no names to give the properties:

public class JSONItemWrapper
{
    [JsonProperty("")]
    public string ID { get; set; }
    [JsonProperty("")]
    public JSONItem MyProperty { get; set; }
}

Edit: "consistent with other methods" The other methods return blocks where every property is within {} and has an identifier. The most recently added function have this "primary key outside of {}" style.

It is a valid json and you can use a type like Dictionary<string, SomeObject> to deserialize your json.

string json = @"{
    ""1001"": {
            ""name"": ""Boots of Speed"",
            ""plaintext"": ""Slightly increases Movement Speed"",
            ""group"": ""BootsNormal"",
            ""description"": ""desc...""
        }
    }";


var dict = JsonConvert.DeserializeObject<Dictionary<string, MyObject>>(json); 

and accesing an item later on by its key can be fast too.


public class MyObject
{
    public string name { get; set; }
    public string plaintext { get; set; }
    public string group { get; set; }
    public string description { get; set; }
}

It's annoying when APIs do things like this (using numbers as property names), but all is not lost. Simply deserialize the JSON using Json.NET and then access each of the items using the indexer operator on the parent object.

EDIT:

I almost never create DTOs when deserializing JSON. It's lots of unnecessary boilerplate in most cases. I prefer deserializing to a dynamic object, but that won't be as effective when dealing with property names that begin with digits.

Here is how I would deserialize your sample message:

using System;

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace JsonExample
{
    internal class Program
    {
        private static void Main()
        {
            const string json = @"
                {
                    '1001': {
                        'name': 'Boots of Speed',
                        'plaintext': 'Slightly increases Movement Speed',
                        'group': 'BootsNormal',
                        'description': '<...'
                    }
                }";
            var jObject = JsonConvert.DeserializeObject<JObject>(json);
            var plaintext = jObject["1001"]["plaintext"].Value<string>();

            Console.WriteLine(plaintext);
        }
    }
}

When put into http://JSONLint.com ,

{
    "1001": {
        "name": "Boots of Speed",
        "plaintext": "Slightly increases Movement Speed",
        "group": "BootsNormal",
        "description": "<..."
    }
}

Validates as JSON.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM