I have a JSON which has a property payload. It holds a JSON as a string like this.
// json schema
{
"id": "GUID",
"type": "some type",
"payload": "{\"name\": \"Smith\", \"age\": 30, ...}" // <- I get a json and serialize it to a string
}
// A C# class for the Json would be...
public class Item
{
public Guid Id { get; set; }
public CustomType Type { get; set; }
public string/JRaw/Anything else? { get; set; }
}
My question is what data type I should use for payload. string or JRaw can be used but
Is there anything else that's better than these types?
Is JRaw better than string? Why/Why not?
Item object will be returned by .NET Core API. A client app gets the response from the API then deserializes it to an object (Item).
payload value can be large. It can be more than 2 ~ 3MB or more.
Between JRaw and string this should be a string. JRaw is in Newtonsoft.Json.Linq namespace and this is not about Linq.
Having said that, you should just return the object:
public class Item<T>
{
public Guid Id { get; set; }
public CustomType Type { get; set; }
public T Data { get; set; }
}
Related
I am reading 2 REST APIs using Httpclient in C#. The APIs return following employee data in JSON format:
1st API
{
"status": "OK",
"content": {
"empid1": 89900,
"empid2": 45550,
"empid3": 22350}
}
2nd API
{
"status": "OK",
"content": {
"empid1": "grade1",
"empid1": "grade2",
"empid1": "grade2"}}
Classes defined and code used is as follows:
public class content
{
public string empid { get; set; } // e.g. empid3
public double salary { get; set; } // e.g. 89900
public string grade { get; set; } // e.g. Grade1
}
public sealed class WrapperEmployees
{
[JsonProperty("status")]
public string Status { get; set; }
[JsonProperty("data")]
public List<content> empdata { get; set; } = new List<data>();
}
To deserialize, used this-
WrapperEmployees nj = JsonConvert.DeserializeObject<WrapperEmployees>(response);
But, last line gives error on deserialization:
Cannot deserialize current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[CsharpSample.App_Code.Employee]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly. To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object. Path 'content.emp1', line 4, position 18.
Is my class structure incorrect?
My ultimate aim is to fetch common data from both APIs against employees.
Option 1: use specific classes for each json deserialization:
class EmployeesSalaries {
public string Status { get; set; }
public Dictionary<string, int> content { get; set; };
}
class EmployeesGrades {
public string Status { get; set; }
public Dictionary<string, string> content { get; set; };
}
Option 2: deserialize to common class, but you will get 'good' content values only if they are int/string. If they will be objects - you will have JObjects as values.
class EmployeesData {
public string Status { get; set; }
public Dictionary<string, object> content { get; set; };
}
How do I deserialize json string to object depends on json content?
I would like to do this with Newtonsoft.Json, since I am using it in the whole project and it is simple for use.
Let me explain by example:
I have json string which can have to be different property object. Content depends on the tool that generates the json files, and I cannot predict the content base on the filename or something like that.
For example, I can have json file:
{
"FileCreationDate":"29-08-2018 14:56:30",
"MessageType":2,
"Messages":[
{
"MessageSequenceNumber":1,
"ModalType":5,
"Message":{
"TransactionValue":5,
"ProductAmount":5
}
}
]
}
Or I can have something like this:
{
"FileCreationDate":"29-08-2018 14:56:30",
"MessageType":1,
"Messages":[
{
"MessageSequenceNumber":1,
"ModalType":5,
"Message":{
"TransactionBusinessDate":"29-08-2018 14:54:29",
"TransactionStatus":5,
"TicketNumber":5,
}
}
]
}
You can see that both json strings have same properties except message object in messages list.
I want to deserialize to this data structure:
public class EventFileDto
{
public string FileCreationDate { get; set; }
public MessageType MessageType { get; set; }
public IEnumerable<MessageDetailsDto> Messages { get; set; }
}
public class MessageDetailsDto
{
public int MessageSequenceNumber { get; set; }
public int ModalType { get; set; }
public EventMessageDto EventMessage { get; set; }
public TransactionMessage TransactionMessage { get; set; }
}
If json string is from the first example I want deserialize message object to EventMessage property, and TransactionMessage property should be null.
In the case of second json string, I want the opposite.
I don't want use dynamic type, since mapping to the entity would be more complicated.
How can this be done?
Thank you for your help.
.Net Fiddle 1
I have a JOSN received from external API as follows
[{
"assignedto": "MAIN STAFF",
"createduser": "API-71",
"departmentid": "1",
"observations": [{
"abnormalflag": "abnormal",
"analytename": "HGB A1C",
"value": "5"
}],
"pages": [],
"priority": "2",
"status": "REVIEW"
}]
I did a Paste Special in Visual Studio and got following classes
public class Rootobject
{
public Class1[] Property1 { get; set; }
}
public class Class1
{
public string assignedto { get; set; }
public string createduser { get; set; }
public string departmentid { get; set; }
public Observation[] observations { get; set; }
public object[] pages { get; set; }
public string priority { get; set; }
public string status { get; set; }
}
public class Observation
{
public string abnormalflag { get; set; }
public string analytename { get; set; }
public string value { get; set; }
}
When I do a deserialization, I am getting following error
Run-time exception (line 24): Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'Rootobject' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
Path '', line 1, position 1.
C# Code
public static void Main(string[] args)
{
var json = #"[{
""assignedto"": ""MAIN ST (HUB) STAFF"",
""createduser"": ""API-7127"",
""departmentid"": ""1"",
""observations"": [{
""abnormalflag"": ""abnormal"",
""analytename"": ""HGB A1C"",
""value"": ""5""
}],
""pages"": [],
""priority"": ""2"",
""status"": ""REVIEW""
}]";
Rootobject resultObj = JToken.Parse(json).ToObject<Rootobject>();
}
I referred similar questions like Create a strongly typed c# object from json object with ID as the name - but that is a different issue.
Any idea how to fix this? Also what is the better way to generate C# classes from JSON?
Note: I also tried with class I got from http://json2csharp.com/. That also faield - Fidlle 2
I would use Newtonsoft / Json convert and change this:
Rootobject resultObj = JToken.Parse(json).ToObject<Rootobject>();
to:
using Newtonsoft.Json;
-- snip --
var resultObj = JsonConvert.DeserializeObject<List<Class1>>(json);
Console.WriteLine(resultObj.Count); // 1
Class1 result = resultObj[0];
Console.WriteLine(result.assignedto); // "MAIN ST (HUB) STAFF"
This will give you a collection of RootObject
As #JeffMeracdo states above - you are providing a collection of object and trying to parse as though it is a single object
As #JeffMeracdo states above, try this:
List<Example> resultObj = JsonConvert.DeserializeObject<List<Example>>(json);
Following using statement and package along with Newtonsoft.Json Nuget package:
using Newtonsoft.Json;
Classes:
public class Observation
{
public string abnormalflag { get; set; }
public string analytename { get; set; }
public string value { get; set; }
}
public class Example
{
public string assignedto { get; set; }
public string createduser { get; set; }
public string departmentid { get; set; }
public List<Observation> observations { get; set; }
public List<object> pages { get; set; }
public string priority { get; set; }
public string status { get; set; }
}
I am trying to deserialise some JSON that I get back from an API so that I can loop through an array of county names and add the information to a datatable in C#. However I am receiving following error at the first hurdle when I try and deserialise it:
error: System.MissingMethodException: No parameterless constructor defined for type of 'DPDJSONLibrary.DPD_JSON+LOCR_Data[]'.
The provider of the API provides an example of the JSON response as follows:
{
"error": null,
"data":[{
"country": [{
"countryCode":"GB",
"countryName":"United Kingdom",
"internalCode":"UK",
"isEUCountry":false,
"isLiabilityAllowed":false,
"isoCode":"826",
"isPostcodeRequired":false,
"liabilityMax":15000
}]
}]
}
A sample of the JSON data I am getting back from the API is:
{
"data": {
"country":[
{
"countryCode":"PM",
"countryName":"St Pierre & Miquilon",
"isoCode":"666",
"isEUCountry":false,
"isLiabilityAllowed":true,
"liabilityMax":15000,
"isPostcodeRequired":true
},
{
"countryCode":"SR",
"countryName":"Suriname",
"isoCode":"740",
"isEUCountry":false,
"isLiabilityAllowed":true,
"liabilityMax":15000,
"isPostcodeRequired":true
},
{
"countryCode":"SZ",
"countryName":"Swaziland",
"isoCode":"748",
"isEUCountry":false,
"isLiabilityAllowed":true,
"liabilityMax":15000,
"isPostcodeRequired":true
}
]
}
}
I have tried to make some classes to put the JSON in as follows:
/// <summary>
/// List Of Countries Response object.
/// </summary>
public class LOCR
{
public LOCR_Error error { get; set; }
public LOCR_Data[] data { get; set; }
}
public class LOCR_Error
{
public string errorAction { get; set; }
public string errorCode { get; set; }
public string errorMessage { get; set; }
public string errorObj { get; set; }
public string errorType { get; set; }
}
public class LOCR_Data
{
public LOCR_Data_Country[] country { get; set; }
}
public class LOCR_Data_Country
{
public string countryCode { get; set; }
public string countryName { get; set; }
public string internalCode { get; set; }
public bool isEUCountry { get; set; }
public bool isLiabilityAllowed { get; set; }
public string isoCode { get; set; }
public bool isPostcodeRequired { get; set; }
public int liabilityMax { get; set; }
}
When I get the JSON back as a string, I am trying to use the Newtonsoft (plugin?) to put it into my classes using:
JavaScriptSerializer ser = new JavaScriptSerializer();
DPD_JSON.LOCR DPDCountries = new DPD_JSON.LOCR();
DPDCountries = ser.Deserialize<DPD_JSON.LOCR>(data);
It is the last line above that is generating the error. I suspect I've written my classes wrong that I am trying to deserialise the JSON in to - can anyone see where I've gone wrong?
Deserialize will return a list and not an array, So your LOCR_Data_Country should be of type List and not array:
public class LOCR_Data
{
public List<LOCR_Data_Country> country { get; set; }
}
There's a HUGE difference between the two example JSON strings you've shown. Mainly the first one is an array : "data":[ ... ] and the second one is an object "data:{ ... }. These two are not interchangeable so you have to stick to either one of those. If the thing you're getting back from the API is an object instead you should rewrite your model to be :
public class LOCR
{
public LOCR_Error error { get; set; }
// object here since "data": { ... }
public LOCR_Data data { get; set; }
}
And as you move further with the JSON you can see that LOCR_Data.country is in fact an array in both cases "country": [ ... ] so you can stick with the current implementation of LOCR_Data class.
Try Using :
YourResultClass object = JsonConvert.DeserializeObject<YourResultClass>(Jsonstring);
See the answer of this Using JsonConvert.DeserializeObject to deserialize Json
OR
dynamic data = Json.Decode(json);
You can refer this Deserialize JSON into C# dynamic object? for further assistance
I'm currently working on a project where I make a request to the Riot Games API, parse the JSON, and do some stuff with it. I have the request working, and I know I'm getting valid JSON. My issue is using JSON.Net to deserialize the JSON.
The JSON is of the following structure:
{
"xarcies": {
"id": 31933985,
"name": "Farces",
"profileIconId": 588,
"revisionDate": 1450249383000,
"summonerLevel": 30
}
}
I want to load this data into the following class
[JsonObject(MemberSerialization.OptIn)]
class Summoner
{
[JsonProperty("id")]
public long id {get;set;}
[JsonProperty("name")]
public string name { get; set; }
[JsonProperty("profileIconId")]
public int profileIconId { get; set; }
[JsonProperty("revisionDate")]
public long revisionDate { get; set; }
[JsonProperty("summonerLevel")]
public long summonerLevel { get; set; }
}
The issue I'm having is that because I'm given a "xarcies" object that contains the information I need, I'm not sure how to go about designing a class that can accept the JSON data. I've seen some examples that use a RootObject class to take the object and that class has a subclass that all the pairs are put into, but I can't seem to get it to work. Every time I run it the attributes for the object end up being NULL.
You can deserialize your JSON as a Dictionary<string, Summoner>:
var root = JsonConvert.DeserializeObject<Dictionary<string, Summoner>>(jsonString);
The dictionary will be keyed by the user name, in this case "xarcies". See Deserialize a Dictionary.
I just used json2csharp to create the following class (its types look a bit different then yours):
public class UserData
{
public int id { get; set; }
public string name { get; set; }
public int profileIconId { get; set; }
public long revisionDate { get; set; }
public int summonerLevel { get; set; }
}
public class RootObject
{
public KeyValuePair<string, UserData> value { get; set; }
}