Deserialising JSON made up of various models C# - c#

I'm trying to work out how to deserialise a JSON response that can be made up of single or multiple models, so for instance, I have the following URL and Response from that endpoint:
https://api.site.com/products?query=fruit
Which would return something such as this:
{
"fruit": [{ ... },{ ... }]
}
"Fruit" could be anything, but as an alternative, you can also do this:
https://api.site.com/products?query=fruit,pies
{
"fruit": [{ ... }, { ... }],
"pies": [{ ... }, { ... }]
}
So I know how to handle just one of the "selections" provided at a time, however how do I go about deserialising the response when there can be 2 separate models in the same response?

In case you know the json model before hand (also called data contract), then you can create a dedicated class. So, for the above scenario, the class would be
public class AnyClassName
{
public List<Fruit> Fruit { get; set; }
public List<Pie> Pie { get; set; }
}
And then use
Newtonsoft.Json.JsonConvert.DeserializeObject<AnyClassName>(jsonString)
In case you are not aware of the data-contract, then use
Newtonsoft.Json.JsonConvert.DeserializeObject(jsonString)
In this case you have to do a lot of coding to probe for the existence of an element and extract the value.

Related

In C#, can I edit/change the types in a json string?

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;
}

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.

Get specific json elements

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

How to Deserialise JSON Data to Array of Model objects?

I have a C#/ASP.Net project using WebAPI2 that has an API endpoint. That endpoint provides an array of JSON objects as a response to a GET request. I use a Model of the native object for serialisation, which is the standard way in WebAPI2 as I understand it.
The serialization happens 'behind the scenes' when I send an OK HttpActionResult typed for an IEnumerable of models,
return Ok<IEnumerable<Model>>(arrayOfModels);
I have a second app that receives the JSON string representation of the array of models. The inbound string to deserialise looks like this, for an array with a single element...
[
{
"ExecID": "EXWB4KT-1",
"Symbol": "CERT-EUR-TEST",
"ExecutionTime": "2016-07-28T14:59:56.24",
"BuyExchID": "IDH64KT-1",
"SellExchID": "IDH64KT-3",
"Tradable": {
"CERT": {
"AccSrc": "ANDY-CERT",
"AccDst": "HIBLET-CERT",
"Qty": "0.01000000",
"State": "PENDING"
},
"EUR1": {
"AccSrc": "HIBLET-EUR",
"AccDst": "ANDY-EUR",
"Qty": "0.33",
"State": "PENDING"
}
}
}
]
How should I rehydrate the JSON data, bearing in mind that I have the WebAPI2 model available in another project?
As I have control of both ends, I am thinking the deserialisation back into an array of models should be trivial, but I am not sure how to do it. I know there are lots of possible ways to do this, I am looking for the sanest or cleanest way.
Try the Newsoft.Json nuget package. Then it's a matter of creating your model and deserializing. Something like this:
public class MyObject
{
int ExecID { get; set; }
string Symbol { get; set; }
//etc etc
}
Then in your method:
using Newtonsoft.Json;
public class MyMethod(string json)
{
List<MyObject> objList = JsonConvert.DeserializeObject<List<MyObject>>(json);
}
This code may not be exact, but should be something similar

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.

Categories