Trying to create model for json - c#

How to create model for this json? I can't understand how to add dictinary to this string array.
{
"ts": 1652718271,
"updates": [
[
4,
508976,
33,
466697301,
1551996353,
"Цацу",
{
"title": " ... ",
"type": "photo"
}
]
]
}

There are a few ways to handle JSON arrays of varied types. One way is to define a class with nullable fields of the types you may encounter in the array. For example,
public class Model
{
public int TS;
public Update[][] Updates;
}
public class Update
{
public int? Number;
public string Word;
public ModelDictionary Dictionary;
}
public class ModelDictionary
{
public string Title;
public string Type;
}
Then you could access each Update with something like
if (Number != null) { ... }
else if (Word != null) { ... }
else if (Dictionary != null) { ... }
Also, https://app.quicktype.io/ is always a great resource for generating C# models from JSON objects.

With this model you can deserialize using Newtonsoft.Json
class Serial
{
public string ts { get; set; }
public object [][] updates { get; set; }
}

Related

REST API Deserialize Nested Response in Newtonsoft.Json

EDIT: Once I have this information deserialized, how can I access the data I need? The only information I need to grab is the TransitTime and the Cost for each accessorial.
I'm working with an API in which I need data from nested objects, but I'm unsure of how to access this information. I've passed my data to the API and have set up new classes based on how the data comes back from the API.
Here's what the response looks like:
{"RatingResponse":
{"Success":"true",
"Message":"",
"QuoteID":"57450",
"LoadNum":"57450",
"Rates":{
"Rate":[
{"SCAC":"TEST",
"CarrierName":"TEST",
"TransitTime":"1",
"ServiceLevel":"D",
"TotalCost":"983.69",
"ThirdPartyCharge":"983.69",
"Accessorials":{
"Accessorial":[
{"Code":"400",
"Cost":"1,655.55",
"Description":"Freight"
},
{"Code":"DSC",
"Cost":"-985.55",
"Description":"Discount"
},
{"Code":"FUE",
"Cost":"313.69",
"Description":"Fuel Surcharge"
}
]
},
"QuoteNumber":""
},
{"SCAC":"TEST2",
"CarrierName":"TEST2",
"TransitTime":"1",
"ServiceLevel":"D",
"TotalCost":"983.69",
"ThirdPartyCharge":"983.69",
"Accessorials":{
"Accessorial":[
{"Code":"400",
"Cost":"1,655.55",
"Description":"Freight"
},
{"Code":"DSC",
"Cost":"-985.55",
"Description":"Discount"
},
{"Code":"FUE",
"Cost":"313.69",
"Description":"Fuel Surcharge"
}
]
},
"QuoteNumber":""
}
]
},
"AverageTotalCost":"983.69"
}
}
I've converted it to C#:
public class Accessorial
{
public string Code;
public string Cost;
public string Description;
}
public class Accessorials
{
public List<Accessorial> Accessorial;
}
public class Rate
{
public string SCAC;
public string CarrierName;
public string TransitTime;
public string ServiceLevel;
public string TotalCost;
public string ThirdPartyCharge;
public Accessorials Accessorials;
public string QuoteNumber;
}
public class Rates
{
public List<Rate> Rate;
}
public class RatingResponse
{
public string Success;
public string Message;
public string QuoteID;
public string LoadNum;
public Rates Rates;
public string AverageTotalCost;
}
public class Root
{
public RatingResponse RatingResponse;
}
The only values I need are the Rate Transit Time and Service Level as well as the Accessorial Costs. I'm a beginner with APIs and am not sure how to return only that information. Any help is greatly appreciated!
you don't need any classes if you use this code
var rate = (JArray)JObject.Parse(json)["RatingResponse"]["Rates"]["Rate"];
var result = rate.Select(r => new
{
TransitTime = (int)r["TransitTime"],
ServiceLevel = (string) r["ServiceLevel"],
AccessorialCost = ((JArray)r["Accessorials"]["Accessorial"]).Select(r => (double)r["Cost"]).ToList()
});
result (in json format)
[
{
"TransitTime": 1,
"ServiceLevel": "D",
"AccessorialCost": [
1655.55,
-985.55,
313.69
]
},
{
"TransitTime": 1,
"ServiceLevel": "D",
"AccessorialCost": [
1655.55,
-985.55,
313.69
]
}
]
or you can create a Data class instead of an anonymous
List<Data> result = rate.Select(r => new Data
{
....
}).ToList();
public class Data
{
public int TransitTime { get; set; }
public string ServiceLevel { get; set; }
public List<double> AccessorialCost { get; set; }
}
I like #Serge's answer but I prefer to have results in a class because "I only need..." never holds for very long, right? Here is a good discussion of loading the JSON into a complex object:
Your JSON erred in JSON2C#.com but essentially your root object needs the other classes. Something like
public class Root
{
public RatingResponse RatingResponse;
public Rates Rates;
public Accessorials Accessorials;
}
and then deserialize into your complex object
JsonConvert.DeserializeObject<RootObject>(json)
I'm doing this off the top of my head so forgive any syntax errors.

Defining List of Enum as DTO Class C#

This is my input JSON response
{
"permissions": {
"user": [
"Add",
"Update",
"Delete"
],
"Product": [
"Read",
"Create"
]
}
}
I'm trying to create the DTO class for the same. So far I've created a set of Enum with the available values
PermissionAction Enum
public enum PermissionAction
{
Add,
Update,
Read,
Delete,
Create
}
PermissionItem Enum
public enum PermissionItem
{
User,
Product
}
How to create a DTO Class for the given JSON Response with the available Enums?
I tired like differently like
public class Permissions
{
public List<PermissionAction> User { get; set; }
public List<PermissionItem> Product { get; set; }
}
Which is wrong.
Since the response may vary dynamically. What I mean that is sometimes a User List will not available and sometimes Product is not available.
Like,
{
"permissions": {
"user": [
"Add",
"Update",
"Delete"
]
}
}
I need to support those kinds of response also with my DTO Class.
UPDATE 1:
I think the JSON which I posted above is confusing others. Sorry for that confusion. Actually, my permissions JSON Object is contained List of Permission Item(s) in which each Permission Items itself again having a List of Permission Actions.
It seems like you need to use binary or (i.e. |) customizing the serialization.
Enum can already parse many names:
[Flags] // <--- Don't forget to apply this attribute if you want masks!
public enum A { X, Y }
Enum.TryParse<A>("X, Y", out var flags);
if(flags.HasFlag(A.X) && flags.HasFlag(A.Y))
{
// It'll enter here!
}
Definitively, you need to customize your deserialization so that flags coming as arrays get turned into a comma-separated capitalized flag string.
That is, you'll end up with this class:
public class Permissions
{
public Permissions(A a, B b)
{
A = a;
B = b;
}
public A A { get; }
public B B { get; }
}
You can do this with Newtosoft.Json that you get from NuGet:
void Main()
{
string json = #"{
""permissions"": {
""user"": [
""Add"",
""Update"",
""Delete""
],
""Product"": [
""Read"",
""Create""
]
}
}";
var root = Root.FromJson(json);
Console.WriteLine("C# Object");
Console.WriteLine("Permissions:");
Console.WriteLine("\tUser:[");
foreach (var v in root.Permissions.User)
{
Console.WriteLine($"\t\t{v}");
}
Console.WriteLine("\t]");
Console.WriteLine("\tProduct:[");
foreach (var v in root.Permissions.Product)
{
Console.WriteLine($"\t\t{v}");
}
Console.WriteLine("\t]");
Console.WriteLine("As JSON string");
Console.WriteLine(root.ToJson());
}
[JsonConverter(typeof(StringEnumConverter))]
public enum UserAction {
Add,
Update,
Delete
}
[JsonConverter(typeof(StringEnumConverter))]
public enum ProductAction
{
Read,
Create
}
public partial class Root
{
[JsonProperty("permissions")]
public Permissions Permissions { get; set; }
public static Root FromJson(string json) => JsonConvert.DeserializeObject<Root>(json);
public string ToJson() => JsonConvert.SerializeObject(this);
}
public class Permissions
{
[JsonProperty("user")]
public List<UserAction> User { get; set ; }
[JsonProperty("Product")]
public List<ProductAction> Product { get; set; }
}

Newtonsoft deserialize object that extends from Collection<Item>

I'm trying to use NewtonSoft.Json deserializer, but I don't know if what I'm trying to do is doable, cuase every example of collections that I've seen are like this:
public class ItemRecords
{
public List<ItemRecords> Items { get; set; }
...
}
And what I want is something that looks like as it's explained below...
I have this two classes:
public class ItemRecords : Collection<ItemRecord>
{
[JsonProperty("property1")]
public int Property1 { get; set; }
[JsonProperty("property2")]
public int Property2 { get; set; }
}
public class ItemRecord
{
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("item_prop1")]
public string ItemProp1 { get; set; }
...
}
I get this json back from my api:
{
property1: 25,
property2: 27,
item_record: [
{
id: 241,
item_prop1: "0.132",
item_prop2: "78787",
...
},
{
id: 242
item_prop1: "1212",
item_prop2: "3333",
...
}
...
]
}
ItemRecords is a collection of ItemRecord.
I tried by adding the JsonArray attribute to the ItemRecords class as follows:
[JsonArray(ItemConverterType = typeof(ItemRecord))]
public class ItemRecords : Collection<ItemRecord> { ... }
Here is the method that executes the request:
private static async Task<T> MakeRequest<T>(string urlRequest)
{
try
{
HttpWebRequest request = WebRequest.Create(urlRequest) as HttpWebRequest;
using (WebResponse response = await request.GetResponseAsync())
{
using (Stream stream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(stream);
string line = string.Empty;
StringBuilder sb = new StringBuilder();
while ((line = reader.ReadLine()) != null)
{
sb.Append(line);
}
T objectDeserialized = JsonConvert.DeserializeObject<T>(sb.ToString());
return objectDeserialized;
}
}
}
catch (Exception ex)
{
return default(T);
}
}
And call to this method looks like this:
...
return await MakeRequest<ItemRecords>(request);
I don't really know what else to do..
Any help would be appreciated.
Your basic difficulty is that the JSON standard has two types of container:
The object which is an unordered set of name/value pairs. An object begins with { (left brace) and ends with } (right brace). Json.NET maps dictionaries and non-enumerable POCOS to objects by default, using reflection to map c# properties to JSON properties.
In the JSON you are getting back from your API, the outermost container is an object.
The array which is an ordered collection of values. An array begins with [ (left bracket) and ends with ] (right bracket). Values are separated by , (comma). Json.NET maps non-dictionary enumerables to arrays by default, serializing each collection item as an array entry.
In the JSON you are getting back from your API, the value of the item_record property is an array.
As a collection with properties, your ItemRecords cannot be mapped to either of these constructs automatically without losing data. Since Json.NET serializes collections as arrays by default, you will need to manually inform it that your type is to be serialized as an object by applying the [JsonObject] attribute. Then, introduce a synthetic item_record property to serialize and deserialize the collection items. Since you are inheriting from Collection<T>, you can use Collection<T>.Items for this purpose:
[JsonObject(MemberSerialization.OptIn)]
public class ItemRecords : Collection<ItemRecord>
{
[JsonProperty("property1")]
public int Property1 { get; set; }
[JsonProperty("property2")]
public int Property2 { get; set; }
[JsonProperty("item_record")]
IList<ItemRecord> ItemRecordList
{
get
{
return Items;
}
}
}
Using MemberSerialization.OptIn prevents base class properties such as Count from being serialized.
Sample fiddle.
As an aside, I don't particularly recommend this design, as it can cause problems with other serializers. For instance, XmlSerializer will never serialize collection properties; see here or here. See also Why not inherit from List?.
Simply add a List<ItemRecord> Records property to class ItemRecords:
public class ItemRecords
{
[JsonProperty("property1")]
public int Property1 { get; set; }
[JsonProperty("property2")]
public int Property2 { get; set; }
[JsonProperty("item_record")]
public List<ItemRecord> Records { get; set; }
}
This looks like you can have a dynamic number of results of properties and item properties like:
{
property1: 25,
property2: 27,
property3: 30,
item_record: [
{
id: 241,
item_prop1: "0.132",
item_prop2: "78787"
},
{
id: 242
item_prop1: "1212",
item_prop2: "3333",
item_prop3: "3333",
item_prop4: "3333",
}
] }
If this is the case, the best option in my opinion will be to change the structure to something like:
{
properties:[
25,
27,
30
],
itemRecords:[
{
id: 27,
itemProperties:[
"321",
"654",
"564"
]
},
{
id: 25,
itemProperties:[
"321",
"654"
]
},
]
}

How to Deserialize a JSON array in C#

I am struggling with a subject that has a lot of variants in this forum but I can't seem to find one that suits me, and I think it's because of the way that my JSON array is :( I'm not an expert but I already manage to "almost" get the end.. I need to get hand in "Status" and "listOfCredDetails" value.
My JSON (is called responseFromServer):
{
"Status": {
"StatusCode":143,
"SubStatus":0,
"Description":"Ok"
},
"ListofCredDetails":
[{
"Client":"a",
"CredID":111,
"CredUserID":"abc"
},
{
"Client":"b",
"CredID":112,
"CredUserID":"def"
},
{
"Client":"c",
"CredID":113,
"CredUserID":"ghi"
}]
}
Then, based on lot of examples in this forum, taking bits and pieces I created my classes:
[Serializable]
public class StatusReturn
{
public int StatusCode { get; set; }
public int SubStatus { get; set; }
public string Description { get; set; }
}
[Serializable]
public class CredDetailsReturn
{
public string Client{ get; set; }
public int CredID{ get; set; }
public string CredUserID{ get; set; }
}
[Serializable]
public class GetUserCredentialDetailsReturn
{
public StatusReturn status;
public List<CredDetailsReturn> listOfCredDetails;
public GetUserCredentialDetailsReturn()
{
status = new StatusReturn();
listOfCredDetails = new List<CredDetailsReturn>();
}
}
Then Am going to deserialize to get
1."Status" and its elements into one object and
2."ListofCredDetails" and its List of elements into one object
and then creating object for "GetUserCredentialDetailsReturn" to return both status(object) and ListofCredDetails(object) at a time.
Can anyone help me understand how can i achieve this i have tried some like below to deserialize and to get Json data into two seperate objects.
But it is not working....
public GetUserCredentialDetailsReturn InvokeRequest(RESTInvokeClass objInvoke)
{
...
...
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
string responseText = streamReader.ReadToEnd();
GetUserCredentialDetailsReturn result = new GetUserCredentialDetailsReturn();
result.status = JsonConvert.DeserializeObject<StatusReturn>(responseText);
result.listOfCredDetails = JsonConvert.DeserializeObject<List<CredDetailsReturn>>(responseText);
return result;
}
}
You need to first change your property names in the class GetUserCredentialDetailsReturnas status to Status and listOfCredDetails to ListofCredDetails.
Then you can try to de-serialize your Json into your class GetUserCredentialDetailsReturnby the code below.
GetUserCredentialDetailsReturn result = new GetUserCredentialDetailsReturn();
result = JsonConvert.DeserializeObject<GetUserCredentialDetailsReturn>(responseText);
You can get your status and listOfCredDetails with in the result.
// result.Status
// result.ListofCredDetails
Hope this will be helpful to you.
[Serializable]
public class GetUserCredentialDetailsReturn
{
public StatusReturn status { get; set; }
public List<CredDetailsReturn> listOfCredDetails { get; set; }
}
JsonConvert.Deserialize<GetUserCredentialDetailsReturn>(json_string)
If you need just some isolated elements of a (say very large) JSON File you need the lower level parts of the JSON Library, for example from Newtonsoft:
using Newtonsoft.Json;
Then create a parser which reads through the JSON Tokens:
var reader = new JsonTextReader(...);
You'll get token by token:
private void nextToken()
{
do
{
if (!reader.Read()) this.importError("unexpected end of file");
}
while (reader.TokenType == JsonToken.Comment);
}
and have to handle this in a Token Parser. For example if you read an array:
private void readMyArray()
{
// StartArray
if (reader.TokenType != JsonToken.StartArray) this.importError("expected start of array '['");
this.nextToken();
while (reader.TokenType != JsonToken.EndArray)
{
this.readMyElement();
}
// EndArray
if (reader.TokenType != JsonToken.EndArray) this.importError("expected end of array ']'");
this.nextToken();
}
This technique is explained in every book about building compilers.

json newtonsoft : Deserialize Object containing a list of string

I have the following issue with this json :
{
"EVTS": {
"EVT": [
{ "ID": "123456",
"KEY1" : "somekey",
"CATEG": [
"cat1",
"cat2",
"cat3"
]
}
]}
}
and this c# class:
public class myClass{
public string ID { get; set; }
public string KEY1 { get; set; }
public list<string> CATEG { get; set; }
}
public class ESObject1
{
[JsonProperty("EVT")]
public List<myClass> EVT { get; set; }
}
public class ESObject0
{
[JsonProperty("EVTS")]
public ESObject1 EVTS { get; set; }
}
}
here i call the deserializer :
ESObject0 globalobject = JsonConvert.DeserializeObject<ESObject0>(json);
But this last code doesnt work, i throws this exception : System.ArgumentException: Could not cast or convert from System.String to System.Collections.Generic.List1[System.String].`
Instead of list<string> i used string [] and only string nothing seems to work.
how can i deserialize this object correctly please.
Thank you.
There doesn't seem to be any apparent problem wit hyour code as this working example illustrates:
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
public class myClass
{
public string ID { get; set; }
public string KEY1 { get; set; }
public List<string> CATEG { get; set; }
}
public class ESObject1
{
[JsonProperty("EVT")]
public List<myClass> EVT { get; set; }
}
public class ESObject0
{
[JsonProperty("EVTS")]
public ESObject1 EVTS { get; set; }
}
class Program
{
static void Main()
{
string json =
#"{
""EVTS"": {
""EVT"": [
{
""ID"": ""123456"",
""KEY1"": ""somekey"",
""CATEG"": [
""cat1"",
""cat2"",
""cat3""
]
}
]
}
}";
ESObject0 globalobject = JsonConvert.DeserializeObject<ESObject0>(json);
foreach (string item in globalobject.EVTS.EVT[0].CATEG)
{
Console.WriteLine(item);
}
}
}
Maybe you just fed a wrong json value to the deserializer which doesn't look like as the one shown in your question. By the way, the one shown i nyour question is invalid JSON as you are missing a , after KEY1 property declaration.
UPDATE:
Now that you have shown your real JSON (coming from http://donnees.ville.quebec.qc.ca/Handler.ashx?id=69&f=JSON) it appears that there's a row where CATEG is not an array of strings but a simple string:
""CATEG"": ""Conférence""
Now that's a pretty bad design because they are mixing arrays and simple properties. I am afraid that in order to deal with this situation you will need to use JObjects and extract the information you need by testing the actual underlying type.
For example:
var obj = JObject.Parse(json);
var events = (JArray)obj["EVTS"]["EVT"];
foreach (JObject evt in events)
{
var categories = evt["CATEG"];
if (categories is JArray)
{
// you've got a list of strings so you can loop through them
string[] cats = ((JArray)categories)
.Select(x => x.Value<string>())
.ToArray();
}
else
{
// you've got a simple string
string cat = categories.Value<string>();
}
}
I have done this many times with many many headaches. My advice is take the json output and use a tool similar to this to write your class for you (http://json2csharp.com/).
Then go over any nullable variables and add nullable type (ex. using int? for int) where needed.

Categories