I get a json object that looks like the following.
{
"result": {
"status": 1,
"teams": [
{
"team_id": 1838315,
"name": "Team Secret",
"tag": "Secret",
"time_created": 1408993713,
"rating": "inactive",
"logo": 543025270456493060,
"logo_sponsor": 540768028333677400,
"country_code": "",
"url": "http://www.teamsecret.gg/",
"games_played_with_current_roster": 0,
"player_0_account_id": 41231571,
"player_1_account_id": 73562326,
"player_2_account_id": 82262664,
"player_3_account_id": 86745912,
"player_4_account_id": 87278757,
"admin_account_id": 5390881,
"league_id_0": 1803,
"league_id_1": 1886,
"league_id_2": 1936,
"league_id_3": 1942,
"league_id_4": 2129,
"league_id_5": 2140,
"league_id_6": 2158,
"league_id_7": 2339,
"league_id_8": 2418,
"league_id_9": 2661,
"league_id_10": 2877
}
]
}
}
I want to use the Newtonsoft json.net libaray to deserialize the object.
Most of it is easy but i am not really sure how to handle the player_X_account_id and the league_id_X.
Both have a more or less unlimited amount of elements.
But as the are not mapped as a list but single elements I am not really sure how to map them into my .Net Object.
I could create a hundred members of each sort but that wouldn't be especially nice.
Preferable i would map them to some sort of Collection, but i have no idea how to accomplish or if it is even possible.
Any idea how to do that?
EDIT: I have no control over the json object i get, it's a call to the SteamWebAPI
You can use extension data feature of JSON.NET:
public class Team
{
public int Team_Id { get; set; }
public string Name { get; set; }
public string Tag { get; set; }
public string Url { get; set; }
//other properties
[JsonExtensionData]
public IDictionary<string, JToken> AdditionalData { get; set; }
}
Then you can check the properties for league and player ids by enumerating AdditionalData property.
I think you can convert it to an dictionary object and access the data.
Dictionary<string, string> values = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
foreach (KeyValuePair<string, object> data in values)
{
var key=data.key;
var value=data.value;
if(key =="teams")
{
foreach(KeyValuePair<string, object> team in data )
{
//do your stuffs here................
}
}
}
But it will be good for you if you keep the player_X_account_id and the league_id_X in teams as object like :
"teams": [
{
your data......,
"players":{
"player_0_account_id": 41231571,
"player_1_account_id": 73562326,
"player_2_account_id": 82262664,
"player_3_account_id": 86745912,
"player_4_account_id": 87278757,
}
"admin_account_id": 5390881,
"league":{
"league_id_0": 1803,
"league_id_1": 1886,
"league_id_2": 1936,
"league_id_3": 1942,
"league_id_4": 2129,
"league_id_5": 2140,
"league_id_6": 2158,
"league_id_7": 2339,
"league_id_8": 2418,
"league_id_9": 2661,
"league_id_10": 2877
}
}
]
In a perfect world you would have control over the JSON structure that you're receiving and you could make it look like this
..."league_id" [['1803','1886','1936']]...
instead of that league_id_x thing that you got going on but I don't know if you got control over that.
In the other hand you could use dynamic variables:
dynamic jsonDe = JsonConvert.DeserializeObject(json);
But it has many downfalls as well.
Related
I have slightly annoying use case.
So, I am calling an API . The APi returns some json, which contains a json object with x amount of fields:
{
"status": "ok",
"result": {
"firstprovider": [ .... ],
"secondprovider": [ ...],
"thirdprovider": [ ... ]
}
}
In this example, only three provider are returned, but I could get more or less than that, and their names may vary. It's quite important that I save those names.
The "providers" inside of "result" are of the same type, so I can easily deserialize those to a certain model.
Now, I would normally expext "result" to be a json array of elements, so I could easily deserialize "result" into a List<LiveShopperEventModel>.
Currently, I made a hacky solution, creating a Dictionary<string,Provider> where the key is the name of the provider, and then I later use selectmany to flatten it into a list.
But, I was wondering if there exists some way in c#, that would allow me to convert the "result", into an array, which would make deserialization a lot simpler for me.
So, does anyone know of a way, or a resource that in c# can help in changing the types of json elements, and in this case, making a json object into a json array, with the fields becoming elements in the list?
Reproducing concept with minimal example
So, let's say my json looks like this:
{
"status": "ok",
"result": {
"firstprovider": [ {"name":"John"}, {"car":"BMW"}, {"surname":"Johnson"} ],
"secondprovider": [ {"name":"Zoe"}, {"car":"Ford"}, {"surname":"johnsøn"}],
"thirdprovider": [{"name":"Elliot"}, {"car":"Volkswagen"}, {"surname":"Jackson"} ]
}
}
Then I can deserialize it as in the following code snippet:
string json = "{\r\n\"status\": \"ok\", \r\n\"result\": { \r\n \"firstprovider\": [ {\"name\":\"John\"}, {\"car\":\"BMW\"}, {\"surname\":\"Johnson\", \"age\":30, \"car\":\"fast\"} ],\r\n \"secondprovider\": [ {\"name\":\"Zoe\"}, {\"car\":\"Ford\"}, {\"surname\":\"johnsøn\", \"age\":31, \"car\":null}], \r\n \"thirdprovider\": [{\"name\":\"Elliot\"}, {\"car\":\"Volkswagen\"}, {\"surname\":\"Jackson\", \"age\":32, \"car\":null} ] \r\n }\r\n }\r\n";
// deserializing to a dictionary
var resultDict = JsonConvert.DeserializeObject<ResultModel>(json);
// and now flattening the structure, so that it is a list of "ProviderModel"
// this is the part that feels hacky to me
var providerModelList = resultDict.result.SelectMany(listOfEvents => {
listOfEvents.Value.Select(Provider =>
{
Provider.provider = listOfEvents.Key;
return Provider;
}).ToList();
return listOfEvents.Value;
}).ToList();
public class ResultModel
{
[JsonProperty("result")]
public Dictionary<string, List<ProviderModel>> result { get; set; }
}
public class ProviderModel
{
public string provider { get; set; }
public string name { get; set; }
public string surname { get; set; }
}
The `selectmany" part feels hacky to me, since, i'm combining linq queries in a way that feels overly complicated
Instead, I think it would be much nicer, is the result class could just look like:
public class ResultModel
{
[JsonProperty("result")]
public List<ProviderModel> result { get; set; }
}
you can try something like this
List<ProviderModel> providerModelList = ((JObject)JObject.Parse(json)["result"])
.Properties()
.Select(x => GetValues(x))
.ToList();
public ProviderModel GetValues(JProperty jProp)
{
var providerModel = new JObject(((JArray)jProp.Value)
.Select(jo => ((JObject)jo).Properties().First()))
.ToObject<ProviderModel>();
providerModel.provider = jProp.Name;
return providerModel;
}
i've this json and i need an help to iterate over Elenco.
This is my json
var json = #"
{
{
"Id": 0,
"Point": "123",
"Elenco": [
{
//useless fields
//...
{
"values_": {
"flat": [
1.0, 2.0
]
},
"idPoint": "123",
},
},
{
//useless fields
//...
{
"values_": {
"flat": [
3.0, 6.0
]
},
"idPoint": "1234",
},
},
{
//Other fields here like values, flat and idPoint for x times
},
]
}
}";
I can easily get Id and Point with
JObject object = JObject.Parse(json);
string point = (string)jsonObject["Point"];
but i need to take flat and idPoint and i don't know how do that.
I also need to iterate over Elenco and I have to find which point equals idPunto.
How can i do? Thanks
The best way to achieve what you are trying to do is go via the route of creating the models that represent your json structure and then use a simple json serializer/deserializer library like JSON.Net to deserialize it and access easily its properties.
From what i see, your json model looks something like this:
public class JsonModel
{
public int Id {get; set;}
public string Point {get; set;}
public IEnumerable<JsonModel2> Elenco {get;set;}
}
public class JsonModel2
{
//useless fields
public JsonModel3 SomeProperty{get; set;}
}
public class JsonModel3
{
//useless fields
// i am assuming here that it is a dictionary as it wasnt clear from the json
public Dictionary<string, JsonModel4> DictProperty{get; set;}
}
public class JsonModel4
{
//useless fields
public IEnumerable<float> Flat{get; set;}
}
i am pretty sure i made a mistake here or there in the way i defined the models above, as i feel that the Json itself is not totally correct or is missing a few key elements. Nonetheless, once you define the models correctly with all the elements in your json as a part of your model, you can simply then use
JsonConvert.DeserializeObject<JsonModel>(json);
this will nicely parse and populate the model values correctly, thereby allowing you to iterate over the model properties like a regular c# object.
I'm developing an app in Xamarin and I have a very simple JSON file made of objects I would like to deserialize in one shot into the C# Class I have in my domain. (I am using the Newtonsoft Json.NET Framework)
Each JSON object has 3 properties: Title, Default and Custom. Title is a simple string, while Custom and Default are a list of pairs.
{
"messages": [
{
"Title": "...",
"Default": {
"lang1": "...",
"lang2": "..."
},
"Custom": {
"lang1": "",
"lang2": ""
}
},
{
"Title": "...",
"Default": {
"lang1": "...",
"lang2": "..."
},
"Custom": {
"lang1": "",
"lang2": ""
}
}
]
}
The C# class only contains those same three properties:
[JsonObject(MemberSerialization.OptIn)]
public class MessageItem
{
[JsonProperty]
public String Title { get; set; }
[JsonConverter(typeof (JsonDictionaryAttribute))]
public Dictionary<string, string> Default { get; set; }
[JsonConverter(typeof(JsonDictionaryAttribute))]
public Dictionary<string, string> Custom { get; set; }
}
Now, as you can see, I have already tried to specifically define the class the JsonConverter should use to deserialize the two Dictionary attributes. Problem is, when I try to deserialize the JToken containing a single "message" object I get a System.InvalidCastException.
I have tried to deserialize it both by invoking
JsonConvert.DeserializeObject<Domain.MessageItem>(messageToken.ToString());
and
messageToken.ToObject<Domain.MessageItem>();
and I'm obviously getting the same result.
By deserializing the single token, though, it works just fine, so I'm pretty sure what I'm doing wrong is something in the flag declarations I am using in the class.
I hope some of you can help me with this! Thanks in advance.
You could either deserialize to dictionary
Dictionary<string, List<MessageItem>> messageItems = JsonConvert.DeserializeObject<Dictionary<string, List<MessageItem>>>(yourJson);
foreach(MessageItem item in messageItems["messages"])
{
Console.WriteLine(item.Title);
}
OR you could write a wrapper class:
[JsonObject(MemberSerialization.OptIn)]
public class MessageItems
{
[JsonProperty("messages")]
public List<MessageItem> Messages { get; set; }
}
and deserialize to that
MessageItems messageItems = JsonConvert.DeserializeObject<MessageItems>(yourJson);
foreach(MessageItem item in messageItems.Messages)
{
Console.WriteLine(item.Title);
}
To get those examples to work I had to remove the [JsonConverter(typeof (JsonDictionaryAttribute))] attributes from your MessageItem class and replace with [JsonProperty].
You have the proper class setup for a single MessageItem, but the JSON you posted is a List<MessageItem>.
Create the following class:
public class MessageList {
[JsonProperty]
public List<MessageItem> messages { get; set; }
}
and use Newtonsoft.Json.JsonConvert.DeserializeObject<MessageList>(messageToken.ToString()) and that should do the trick.
I couln't find a similar case here, hence my question. I have a json like this:
{
"prop1": "bla",
"propn": "bla",
"Data": {
"42": {
"prop1": "bla",
"prop2": "bla",
"Symbol": "42"
},
"abc": {
"prop1": "bla",
"prop2": "bla",
"Symbol": "abc"
}
},
"Type": 100
}
Now, how do I get all elements from Data, and the most I am interested in the ones that have the symbol property set. I tried Newtonsoft.json.linq and jobject, but got really no clue what to do here. Any guidance anyone? Thanks!
Ronald
What you're looking for is called 'deserialize'. You have a string (the json in you post) and you want to turn it into an object.
The first steps you need to do are:
Create a class that matches your data.
Simply copy your json string in your post and use the option in Visual Studio to 'paste JSON as class'. Perhaps clean it up by changing the name RootObject to something more descriptive.
Install the NuGet package Newtonsoft in Visual Studio.
Now you can use MyClass myObject = JsonConvert.DeserializeObject<MyClass>(myString);
To access Symboljust use myObject.Data.Symbol
I imagine that once you extract partial data from json, if you still need to pass the data through your application, a dedicated model will come handy.
public class Data
{
public Element abc { get; set; }
}
public class Element
{
public string prop1 { get; set; }
public string prop2 { get; set; }
public string Symbol { get; set; }
}
While you certainly can rely on JObject handling the deserialization, i find it more intuitive to work with anonymous templates, especially for partial data retrieval.
var template = new
{
Data = default(Data)
};
var instance = JsonConvert.DeserializeAnonymousType(json, template);
will give you something like
I recomend you to use Jil library, is faster and more simple than Newtonsoft.json
I have a Json service I cannot alter as it is not mine.
Their Json is a formatted in a way that parsing it is difficult. It looks something like this.
"people": {
"Joe Bob": {
"name": "Joe Bob",
"id": "12345"
},
"Bob Smith": {
"name": "Bob Smith",
"id": "54321"
}
},
I would really prefer this was laid out like a JSon array, however it presently is not.
I am wondering the best approach here. Should I alter the Json to look like an array before I parse it or load up the ExtensionData and parse it from that?
There are other items in the feed that I do not have issue with. Just stuck with this one section.
Thanks
You can use json.net to deserialize the data (the json you pasted, and doing only one parsing, without modifying anything).
using dynamic foo = JsonConvert.DeserializeObject<dynamic>(data)
than, you can iterate the list using foo.people, accessing the Name and Value.
you can create a class (if you know what the schema is, and to deserialize the data into a list of the given class such as:
public class People
{
[JsonProperty(PropertyName="people")]
public IDictionary<string, Person> Persons { get; set; }
}
public class Person
{
[JsonProperty(PropertyName="name")]
public string Name { get; set; }
[JsonProperty(PropertyName = "id")]
public string Id { get; set; }
}
and than call:
var obj = JsonConvert.DeserializeObject<People>(data);
foreach (var item in obj.Persons.Values)
{
//item is instance of Person
}
Another good and possible option will be:
How can I navigate any JSON tree in c#?