Deserializing JSON when inner property names vary - c#

I have JSON which looks something like this (external JSON beyond my control):
[
{
"currencies": {
"KGS": {
"name": "Kyrgyzstani som",
"symbol": "с"
}
}
},
{
"currencies": {
"SOS": {
"name": "Somali shilling",
"symbol": "Sh"
}
}
}
]
And I have a set of classes which I would like this JSON deserialized into
public class ParentClass
{
public OuterClass Currencies { get; set; }
}
public class OuterClass
{
//Inner property below needs to map to these changing prop names: "KGS", "SOS"
public InnerClass Inner { get; set; }
}
public class InnerClass
{
public string Name { get; set; }
public string Symbol { get; set; }
}
And Lastly, when I try to deserialize:
JsonConvert.DeserializeObject<IList<ParentClass>>(responseBody.Content);
It's not deserializing properly, because the it cannot map varying Property names to "Inner". Is there a way to handle this scenario?

Newtonsoft didn't seem to have any problem with it..
public partial class Blah
{
[JsonProperty("currencies")]
public Dictionary<string, Currency> Currencies { get; set; }
}
public partial class Currency
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("symbol")]
public string Symbol { get; set; }
}
And
var blah = JsonConvert.DeserializeObject<Blah[]>(jsonString);
..though it's probably worth noting I think you have your parent and outer the wrong way round if this json is just a fragment..

Related

Dynamic json property deserialize

I'm having difficulties figuring out how to deserialize a json, that has a dynamic property (for example - UserRequest::567) the property name can be any value and the UserRequest object contains other json properties that are of interest to me
I tired writing a class and I don't know what to do with that property. What are the best practices for coping with a problem like this?
{
"objects": {
"UserRequest::567": {
"code": 0,
"message": "created",
"class": "UserRequest",
"key": "567",
"fields": {
"ref": "R-000567",
"org_id": "4"
}
}
}
}
The question is what are the best practices to read through this kind of a json string?
Thank you
To Deserialize this using Newtonsoft.Json, here are the classes:
public class CreateRequest
{
public long code { get;set; }
public string message { get; set; }
[JsonProperty("class")]
public string class1 { get; set; }
public string key { get; set; }
public Fields fields { get; set; }
}
public class Fields
{
[JsonProperty("ref")]
public string refe { get; set; }
public string org_id { get; set; }
}
public class Root
{
public Dictionary<string, CreateRequest> objects { get; set; }
//The 'string' key in the dictionary is the 'UserRequest::567'
}
Then to Deserialize use:
var x = Newtonsoft.Json.JsonConvert.DeserializeObject<Root>(jsonObject).objects.Values;

C# expando creating from JSON with validity check against Linked Classes model

I have the below rather simple build of classes, they represent a model, kindly note the linked classes (initialization included in appropriate instance constructors of each one):
public class DataClass
{
public int num { get; set; }
public string code { get; set; }
public PartClass part { get; set; }
public MemberClass member { get; set; }
public DataClass()
{
part = new PartClass();
member = new MemberClass();
}
}
public class PartClass
{
public int seriesNum { get; set; }
public string seriesCode { get; set; }
}
public class MemberClass
{
public int versionNum { get; set; }
public SideClass side { get; set; }
public MemberClass()
{ side = new SideClass(); }
}
public class SideClass : IMPropertyAsStringSettable
{
public string firstDetail { get; set; }
public string secondDetail { get; set; }
public bool include { get; set; }
public SideClass()
{ }
}
My problem is rather straightforward, however, the complication is on the implementation: I am creating a class dynamically, expando, and I read a JSON which, sometimes, is equivalent one-on-one with the DataClass hierarchy, like:
{
"num": "3",
"code": "some sort of string",
"part": {
"seriesNum": "3",
"seriesCode": "sample"
},
"member": {
"versionNum": "1.5",
"side": {
"firstDetail": "aFirst",
"secondDetail": "aSecond",
"include": "true"
}
}
}
and sometimes, only a few values are equivalent (being a sub-set of DataClass is not an error, if there is an unknown tag in JSON, this is an error - like for example, find "age": "18" in JSON, because DataClass does not contain anywhere an 'age' property etc.), like for example:
{
"num": "9",
"part": {
"seriesNum": "3",
},
"member": {
"versionNum": "1.5",
"side": {
"include": "true"
}
}
}
As said, I don't care if a property - or a whole tree of properties - is missing from the JSON compared to the DataClass.
My problem is, how to read the JSON and assign properties and values in expando, while checking that both the hierarchy as well as the property name are correct.
Could you help me please with this?

JsonConvert deserialize only Class fields

This is json:
{
"odata.metadata": ".....",
"value": [
{
"AbsEntry": 10,
"ItemNo": "....",
"UoMEntry": -1,
"Barcode": "2000000000022",
"FreeText": "Ean13"
}
]
}
This is class:
public class BarCode
{
public int AbsEntry { get; set; }
public string ItemNo { get; set; }
public string Barcode { get; set; }
public string FreeText { get; set; }
}
This method return null:
BarCode barcode = JsonParser.DeserializeObjcet<BarCode>(json);
Are there any properties or other that can cause the call DeserializeObject to deserialize me only the fields of my classes (the names are exactly those of the Json)?
You need to create class like below not BarCode
public class Value
{
public int AbsEntry { get; set; }
public string ItemNo { get; set; }
public int UoMEntry { get; set; }
public string Barcode { get; set; }
public string FreeText { get; set; }
}
or you can change the JSON format
"BarCode": [
{
"AbsEntry": 10,
"ItemNo": "....",
"UoMEntry": -1,
"Barcode": "2000000000022",
"FreeText": "Ean13"
}
]
The structure of your class should match the structure of your JSON if you want the deserialization to succeed.
If you want a partial deserialization e.g. only deserializing the values property into your class you can use this code:
JObject jObject = JObject.Parse(json);
BarCode barcode = jObject["values"].Children().First().ToObject<BarCode>();
With this solution you don't need to refactor your class or adding a new one.
You are missing the root object :
public class RootObject
{
public string __invalid_name__odata.metadata { get; set; }
public List<BarCode> value { get; set; }
}
note that the invalid name oprperty can just be remove so it will be igrored!
Even if you want only the Value part you will have to deserialise from the root, then navigate to the child properties you need.

How to get inner field's value of object by using JsonProperty

I have data in json like this:
{
"data": {
"name" : "Car wash"
"changed_by": {
"id": 1,
"name": "Pascal",
"type": "user"
}
}
}
The value "Car wash" I can get like this:
public class Changes
{
[JsonProperty("name")]
public string name { get; set; }
}
How I can get the value of some changed_by object field?
I need to use this in deserializing
private void GetChanges(RawData data)
{
var changes = JsonConvert.DeserializeObject<Response<IEnumerable<Model.Json.Changes>>>(data.ChangesData);
/* some code */
}
You just need to have a class that represents the changed_by object. For example:
public class Data
{
public string name { get; set; }
public ChangedBy changed_by { get; set; }
}
public class ChangedBy
{
public int id { get; set; }
public string name { get; set; }
public string type { get; set; }
}
Create a class hierarchy representing the structure of the data in and then use Json.Net to deserialize it into an object of this class.
Check out Json.Net

JSON parsing object to string - preserve order of elements

I have this class that needs to be serialized to json:
[DataContract]
public class InfoRequest
{
[DataMember]
public string folder_id { get; set; }
[DataMember]
public string file_type_id { get; set; }
[DataMember]
public string prefix { get; set; }
[DataMember]
public fileInfo[] files;
[DataMember]
public termInfo[] terms;
}
[DataContract]
public class fileInfo
{
[DataMember]
public string name { get; set; }
[DataMember]
public string size { get; set; }
}
[DataContract]
public class termInfo
{
[DataMember]
public string term_id { get; set; }
[DataMember]
public string value { get; set; }
}
I have tried ServiceStack.Text, NewtonSoft.Json, and DataContractJsonSerializer. I get different results from each library, and none of them preserve the order of the DataMembers. (ServiceStack doesn't even serialize all the DataMembers.)
Passing the same InfoRequest object to each library, I get these strings:
JsonConvert:
{
"files":[
{
"name":"Blip.txt",
"size":"448"
},
{
"name":"blip.jpg",
"size":"71535"
}
],
"terms":[
{
"term_id":"1000",
"value":"Copyright"
},
{
"term_id":"1000",
"value":"Copyright"
}
],
"folder_id":"11245",
"file_type_id":"234",
"prefix":"",
"ServiceStack":{
"folder_id":"11245",
"file_type_id":"234",
"prefix":""
},
"MS":{
"file_type_id":"234",
"files":[
{
"name":"Blip.txt",
"size":"448"
},
{
"name":"blip.jpg",
"size":"71535"
}
],
"folder_id":"11245",
"prefix":"",
"terms":[
{
"term_id":"1000",
"value":"Copyright"
},
{
"term_id":"1000",
"value":"Copyright"
}
]
}
}
I suspect the order of DataMembers should not matter, but I'm getting an error from the server, and think that this might be the issue.
Any insight would be appreciated...
Note ServiceStack's JSON Serializer only serializers public properties by default, if you want to include public fields as well (e.g. so it serializers 'files' and 'terms' as well) you need to include:
ServiceStack.Text.JsConfig.IncludePublicFields = true;
DataMembers does affect serialization in ServiceStack which makes all fields opt-in, use IgnoreDataMember if you want to opt-out.

Categories