I'm having a bit of a problem with serializing my .NET objects into JSON using JSON.NET. The output I want to be serialized will have to look like this:
{"members":[
{"member":
{
"id":"4282",
"status":"1931",
"aktiv":"1",
"firmanavn":"firmname1",
"firmaUrl":"www.firmurl.dk",
"firmaUrlAlternativ":"",
"firmaSidstKontrolleretDato":"30-08-2010",
"firmaGodkendelsesDato":"07-03-2002"
}
},
{"member":
{
"id":"4283",
"status":"1931",
"aktiv":"1",
"firmanavn":"firmname2",
"firmaUrl":"www.firmurl.dk",
"firmaUrlAlternativ":"",
"firmaSidstKontrolleretDato":"30-08-2010",
"firmaGodkendelsesDato":"18-12-2000"
}
},
...... long list of members omitted
My .NET structure for now (still experimenting to get the right output) is like this:
public class Members
{
public List<Member> MemberList { get; set; }
}
and:
public class Member
{
[JsonProperty(PropertyName = "Id")]
public string Id { get; set; }
[JsonProperty(PropertyName = "Status")]
public string Status { get; set; }
[JsonProperty(PropertyName = "Aktiv")]
public string Aktiv { get; set; }
[JsonProperty(PropertyName = "Firmanavn")]
public string Firmanavn { get; set; }
[JsonProperty(PropertyName = "FirmaUrl")]
public string FirmaUrl { get; set; }
[JsonProperty(PropertyName = "AltFirmaUrl")]
public string AlternativFirmaUrl { get; set; }
[JsonProperty(PropertyName = "FirmaSidstKontrolleretDato")]
public string FirmaSidstKontrolleretDato { get; set; }
[JsonProperty(PropertyName = "FirmaGodkendelsesDato")]
public string FirmaGodkendelsesDato { get; set; }
}
What the above .NET structure gives me when calling:
string json = JsonConvert.SerializeObject(members, Newtonsoft.Json.Formatting.Indented);
Where 'members' is a list of members. Is this:
{
"Members": [
{
"Id": "1062",
"Status": "1933",
"Aktiv": "1",
"Firmanavn": "firmname",
"FirmaUrl": "http://www.firmurl.dk",
"AltFirmaUrl": "http://www.altfirmurl.dk",
"FirmaSidstKontrolleretDato": "13-09-2011",
"FirmaGodkendelsesDato": "13-09-2511"
},
{
"Id": "1060",
"Status": "1933",
"Aktiv": "1",
"Firmanavn": "firmname2",
"FirmaUrl": "http://www.firmurl.dk",
"AltFirmaUrl": "http://www.altfirmurldk",
"FirmaSidstKontrolleretDato": "13-09-2011",
"FirmaGodkendelsesDato": "13-09-2511"
},
So basically, the structure is right in that it creates the array of members as expected, but I am missing the "member": label on each of the member objects. Is there any way to make such a label? Some kind of class declaration, or something?
I hope my question is clear, if not - please let me know and I'll try to explain further.
Thanks a lot in advance.
/ Bo
It sounds like you just need to make an intermediary object with a property of that name to get the JSON you want; however, I'd consider using the JSON.net originally rendered JSON (as it is structurally better).
Related
I am using JObject to read various api responses. With the following json
{"API":{"Year":["2020","2019","2018","2017","2016","2015"],
"Status": {"Message":"The call returned successfully with years"}}}
I can use this:
dynamic json= JObject.Parse(s);
string[] yrs = json.API.Year.ToObject<string[]>();
where s is the json object.
This works perfectly to give me a simple array of years.
I am having difficulty parsing multi dimensions in the json response. when i have the following:
{"API":{"Category":[
{"GroupName":"Exterior Accessories","GroupID":"2",
"Items":
[{"Id":"64","Value":"Body Part"},
{"Id":"20","Value":"Body Styling"},
{"Id":"7","Value":"Bras and Hood Protectors"}]
},
{"GroupName":"Interior Accessories","GroupID":"4",
"Items":
[{"Id":"21","Value":"Carpet",
{"Id":"2","Value":"Doors and Components"},
{"Id":"8","Value":"Floor Protection"}]
},
],
"Status": {"Message":"The call (api.v12.estore.catalograck.com) returned successfully with categories.","DataFound":true,"TimeStamp":"02/02/2020 11:48:27","InternalError":false}}}
How can I parse this into a multi-dimensional array?
Since Years you used was a simple built in element (string), you dont need to create any classes.. but the Categories you have in your JSON is a object. To access the Categories in a way you can access its elements, I would recommend creating the necessary classes and then using the Category list of the root object to do what you need.
Example code
public class Item
{
public string Id { get; set; }
public string Value { get; set; }
}
public class Category
{
public string GroupName { get; set; }
public string GroupID { get; set; }
public List<Item> Items { get; set; }
}
public class Status
{
public string Message { get; set; }
public bool DataFound { get; set; }
public string TimeStamp { get; set; }
public bool InternalError { get; set; }
}
public class API
{
public List<Category> Category { get; set; }
public Status Status { get; set; }
}
public class RootObject
{
public API API { get; set; }
}
Above are the needed classes for succesful deserialization where RootObject class is the parent.
Use the following in your Main method.,
RootObject root = JsonConvert.DeserializeObject<RootObject>(json);
List<Category> categories = root.API.Category;
I'm pretty new to json so this might be a duplicate. I apologize in advance, but I just don't know how to search for this.
I have the following json file that I have to serialize:
{
"filename":"myFileName.txt",
"sourceProperties":{
"properties":[
{
"key": "myKey0",
"value": "myValue0"
},
{
"key": "myKey1",
"value": "myValue1"
}
]
},
}
I declared two classes to resemble that object:
class Document
{
[JsonProperty(PropertyName = "filename")]
public string Filename { get; set; }
[JsonProperty(PropertyName = "sourceProperties")]
public List<DocProperty> Properties { get; set; }
}
class DocProperty
{
[JsonProperty(PropertyName = "key")]
public string Key { get; set; }
[JsonProperty(PropertyName = "value")]
public string Value { get; set; }
}
But of course the lists tag "properties", which is required in the json file, does not show.
What is the correct way to declare my object, that I get the "sourceProperties" tag, followed by the "properties" tag and list?
Something like this:
class Document
{
[JsonProperty(PropertyName = "filename")]
public string Filename { get; set; }
[JsonProperty(PropertyName = "sourceProperties")]
public SourceProperties Source { get; set; }
}
class SourceProperties
{
[JsonProperty(PropertyName = "properties")]
public Dictionary<string, string> Properties { get; set; }
}
I intentionally replaced List<DocProperty> by Dictionary class, because it's format self-descriptive, and matches structure of your JSON file, but you can use List<DocPropety> if you really want.
.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'd like to consume a REST Api and deserialize the nested JSON Response. For that purpose I tried to create some POCO classes which represent the JSON Response [1].
The response looks like this:
{
"success": true,
"message": "OK",
"types":
[
{
"name": "A5EF3-ASR",
"title": "ITIL Foundation Plus Cloud Introduction",
"classroomDeliveryMethod": "Self-paced Virtual Class",
"descriptions": {
"EN": {
"description": "some Text null",
"overview": null,
"abstract": "Some other text",
"prerequisits": null,
"objective": null,
"topic": null
}
},
"lastModified": "2014-10-08T08:37:43Z",
"created": "2014-04-28T11:23:12Z"
},
{
"name": "A4DT3-ASR",
"title": "ITIL Foundation eLearning Course + Exam",
"classroomDeliveryMethod": "Self-paced Virtual Class",
"descriptions": {
"EN": {
"description": "some Text"
(...)
So I created the following POCO classes:
public class Course
{
public bool success { get; set; }
public string Message { get; set; }
public List<CourseTypeContainer> Type { get; set; }
}
/* each Course has n CourseTypes */
public class CourseType
{
public string Name { get; set; }
public string Title { get; set; }
public List<CourseTypeDescriptionContainer> Descriptions { get; set; }
public DateTime LastModified { get; set; }
public DateTime Created { get; set; }
}
public class CourseTypeContainer
{
public CourseType CourseType { get; set; }
}
/* each CourseType has n CourseTypeDescriptions */
public class CourseTypeDescription
{
public string Description { get; set; }
public string Overview { get; set; }
public string Abstract { get; set; }
public string Prerequisits { get; set; }
public string Objective { get; set; }
public string Topic { get; set; }
}
public class CourseTypeDescriptionContainer
{
public CourseTypeDescription CourseTypeDescription { get; set; }
}
And this is the API Code:
var client = new RestClient("https://www.someurl.com");
client.Authenticator = new HttpBasicAuthenticator("user", "password");
var request = new RestRequest();
request.Resource = "api/v1.0/types";
request.Method = Method.GET;
request.RequestFormat = DataFormat.Json;
var response = client.Execute<Course>(request);
EDIT 1: I found a Typo, the Type property in AvnetCourse should be named Types:
public List<AvnetCourseTypeContainer> Type { get; set; } // wrong
public List<AvnetCourseTypeContainer> Types { get; set; } // correct
Now the return values look like:
response.Data.success = true // CORRECT
repsonse.Data.Message = "OK" // CORRECT
response.Data.Types = (Count: 1234); // CORRECT
response.Data.Types[0].AvnetCourseType = null; // NOT CORRECT
EDIT 2: I implemented the Course.Types Property using a List<CourseType> instead of a List<CourseTypeContainer>, as proposed by Jaanus. The same goes for the CourseTypeDescriptionContainer:
public List<CourseTypeContainer> Type { get; set; } // OLD
public List<CourseTypeDescriptionContainer> Descriptions { get; set; } // OLD
public List<CourseType> Type { get; set; } // NEW
public List<CourseTypeDescription> Descriptions { get; set; } // NEW
Now the response.Data.Types finally are properly filled. However, the response.Data.Types.Descriptions are still not properly filled, since there is an additional language layer (e.g. "EN"). How can I solve this, without creating a PACO for each language?
EDIT 3: I had to add an additional CourseTypeDescriptionDetails class, where I would store the descriptive Data. In my CourseTypeDescription I added a property of the Type List for each language. Code Snippet:
public class AvnetCourseType
{
public List<CourseTypeDescription> Descriptions { get; set; }
// other properties
}
public class CourseTypeDescription
{
public List<CourseTypeDescriptionDetails> EN { get; set; } // English
public List<CourseTypeDescriptionDetails> NL { get; set; } // Dutch
}
public class CourseTypeDescriptionDetails
{
public string Description { get; set; }
public string Overview { get; set; }
public string Abstract { get; set; }
public string Prerequisits { get; set; }
public string Objective { get; set; }
public string Topic { get; set; }
}
It works now, but I need to add another property to CourseTypeDescription for each language.
OLD: The return values are
response.Data.success = true // CORRECT
repsonse.Data.Message = "OK" // CORRECT
response.Data.Type = null; // WHY?
So why does my response.Type equal null? What am I doing wrong?
Thank you
Resources:
[1] RestSharp Deserialization with JSON Array
Try using this as POCO:
public class Course
{
public bool success { get; set; }
public string message { get; set; }
public List<CourseTypeContainer> Types { get; set; }
}
Now you have list of CourseTypeContainer.
And CourseTypeContainer is
public class CourseTypeContainer
{
public CourseType CourseType { get; set; }
}
So when you are trying to get response.Data.Types[0].AvnetCourseType , then you need to have field AvnetCourseType inside CourseTypeContainer
Or I think what you want is actually this public List<CourseType> Types { get; set; }, you don't need a container there.
Just in case this helps someone else, I tried everything here and it still didn't work on the current version of RestSharp (106.6.2). RestSharp was completely ignoring the RootElement property as far as I could tell, even though it was at the top level. My workaround was to manually tell it to pull the nested JSON and then convert that. I used JSON.Net to accomplish this.
var response = restClient.Execute<T>(restRequest);
response.Content = JObject.Parse(response.Content)[restRequest.RootElement].ToString();
return new JsonDeserializer().Deserialize<T>(response);
I used http://json2csharp.com/ to create C# classes from JSON.
Then, renamed RootObject to the ClassName of the model file I'm creating
All the data in the nested json was accessible after RestSharp Deserializitaion similar to responseBody.data.Subject.Alias
where data, Subject and Alias are nested nodes inside the response JSON received.