Deserialize JSON into C# class containing two Dictionary properties - c#

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.

Related

How get Json nested elements

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.

Deserializes JSON to an object in c# using json.net

I am trying to convert my json into a rule object. I have been following this guide from Newtonsoft http://www.newtonsoft.com/json/help/html/deserializeobject.htm.
public class Rule{
public string Field { get; set; }
public string Test { get; set; }
public Rule[] Cases { get; set; }
}
public class Rules {
public List<Rule> Root{ get; set; }
}
My Json from rules.js
{
"Rules": [{
"Field": "Subject",
"Test": "^(Azure Exception)",
"Cases": [{
"Field": "Content",
"Test": "Hostname: az.....(?<Hostname>[^\n])",
"Cases": [{
"Field": "Content",
"Test": "Hostname:\\s+(?<Hostname>.*)\\s+Site name:\\s+(?<SiteName>.*)"
}]
}]
}]
}
In my main method:
String RulesFile = "cSharp/rules.js";
String Json = System.IO.File.ReadAllText(RulesFile);
Rule rule = JsonConvert.DeserializeObject<Rule>(Json);
var rules = JsonConvert.DeserializeObject<Rules>(Json);
//rule.Cases
//rule.Field
//rule.Test
//rules.Root
Console.Write(rule.Field);
I've tested my json and i can output it in my terminal. I'm unsure how to assign each field in json to my rules objects. Looking at the newtonsoft docs this should work, but I'm not getting any output.
I want to be able to print these fields out, anyone know to do it?
Cheers all in advance.
In your JSON string, the root object is an object with a Rules property. That property is an array of objects. You need to define and deserialize the root object, eg
class Rules
{
public Rule[] Rules{get;set;}
}
var rules = JsonConvert.DeserializeObject<Rules>(Json);
You can generate the DTOs requires for deserialization in Visual Studio by copying the JSON string and select Paste JSON as Classes in the Edit menu. You can also generate classes by using an online converter like json2csharp

Parsing Json .Net Web Api

I'm new with Web API 2 / Entity Framework 6 project, I'm making REST services, but for one specific service I'm going to receive (via Post) a JSON before making any CRUD operations over any entity of the model, (have to make some business validations over the data, add or complement some things and decide on wich entity to save), the JSON is:
{
"head": {
"action": "create",
"object": "oneobject",
"user": "theuser"
},
"object": {
"name1": "a name 1",
"name2": "a name 2",
"description": "a description here"
},
"rule": [{
"name": "any name",
"value": "any value"
}, {
"name": "another name",
"value": "another value"
}]
}
So the json not maps directly to an entity, in fact I have no model or object for this. What would be the better way to work with it? I mean how to receive and parse the json. I'm new with web api and rest services, and I would appreciate you can help me and explain me with good details. Thanks guys.
Edit:
Any idea of the POCO or class that match this kind of json. ("rule" list It's variable, can be one or more).
After create this poco or class I would have to make a controller based on this?
As others have said, what you need is a POCO object to represent your request. Based on the information you have provided the following should achieve close enough to what you are after:
public enum CrudAction
{
Create,
Read,
Update,
Delete
}
public sealed class CrudRequestHeader
{
public CrudAction Action { get; set; }
public string Object { get; set; }
public string User { get; set; }
}
public sealed class RuleDefinition
{
public string Name { get; set; }
public string Value { get; set; }
}
public sealed class CrudRequest
{
public CrudRequestHeader Head { get; set;}
public Dictionary<string, string> Object { get; set; }
public List<RuleDefinition> Rule { get; set; }
}
In your Web API controller method you can then take a parameter of type CrudRequest and your JSON will be deserialized to this object, e.g:
public IHttpActionResult Post(CrudRequest crudRequest)
{
// TODO Implementation
}
You may notice I have used Dictionary<string, string> for CrudRequest.Object as it is variable how many key/values we will be supplied with, I have made the assumption that all values are strings, you can use an object value if you prefer but you will then need to handle the type of value. In the same principle I have used List<RuleDefinition> for CrudRequest.Rule to cater for the variable number of rules which may be supplied.
A LINQPad sample containing the above definitions and use with your input can be found here: http://share.linqpad.net/7rvmhh.linq
Although the JSON may not represent a logical entity in your model, you clearly have a mental model of the "shape" of the JSON data - I say this because you define it in your code snippet. You should create a POCO (plain old C# object) to represent this model, and deserialize the incoming JSON request to an object of that type. Once you've deserialized it to your object, it will be trivial to work with this data using object properties and such.
The best thing to do would be to create a class that models the object you expect back.
This way in your Web API method you can use the [FromBody] attribute to automatically parse the body of the request.
Example -
Your data contract would look like this:
public class MyContract
{
public string MyData { get; set;}
}
In your ApiController
[HttpPost]
[Route("api/myobject")]
public async Task ReceiveMyObject([FromBody]MyContract object) {
var data = object.MyData;
// Do whatever you need to do here.
}
This may seem tedious but this will let you keep your code organized.
Edit
So to create a contract out of this:
{
"head": {
"action": "create",
"object": "oneobject",
"user": "theuser"
},
"object": {
"name1": "a name 1",
"name2": "a name 2",
"description": "a description here"
},
"rule": [{
"name": "any name",
"value": "any value"
}, {
"name": "another name",
"value": "another value"
}]
}
You would do something like this:
public class MyContract
{
[JsonProperty("head")]
public MetaObject Head
{
get; set;
}
// Not sure if this will work, but it probably will
[JsonProperty("object")]
public JObject ExtendedInformation
{
get;
set;
}
[JsonProperty("rule")]
public Rule[] Rules
{
get;
set;
}
}
// "MetaObject" definition omitted but you can understand my point with the below
public class Rule
{
[JsonProperty("name")]
public string Name
{
get;
set;
}
[JsonProperty("value")]
public string Value
{
get;
set;
}
}
Usually a REST service issue a contract, which means some kind of metadata to describe the content of its messages, otherwise you cannot call this as a RESTful Web API. Take a look at this post from Roy Fielding, who created the term of REST API, if you want to know better what is REST and what is not.
So if your service is a true REST service you should be able to have a description somewhere that give you the possibility to parse the media.
However, if you still cannot find any way to understand how the JSON should be interpreted you may be able to use it inside a C# class anyway: take a look at the JObject class from Newtonsoft.Json that enables to use a dynamic object at runtime.
Basically, it is used like this:
using Newtonsoft.Json.Linq; // This needs the Newtonsoft.Json package
dynamic entity = JObject.Parse(jsonString);
string value = entity.key1;
string value2 = entity["key2"];
I did this simple demo with your data.
You can also check the full documentation of the class on the Newtonsoft website.

json.net map elements to collection

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.

Alter Json or ExtensionDataObject

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#?

Categories