How to retrieve following json string to separate objects in c# - c#

hotel_pricesURL = string_builder.ToString();
RootobjectOne robjectOne = JsonConvert.DeserializeObject<RootobjectOne>(hotel_pricesURL);
List<OneStar> one_star_list = new List<OneStar>();
var check = robjectOne.onestar;
foreach(var items in check)
{
}
Including RootobjectOne class:
public class RootobjectOne
{
[JsonProperty("OneStar")]
public OneStar onestar { get; set; }
[JsonProperty("TwoStar")]
public TwoStar twostar { get; set; }
[JsonProperty("ThreeStar")]
public ThreeStar threestar { get; set; }
[JsonProperty("FourStar")]
public FourStar fourstar { get; set; }
[JsonProperty("FiveStar")]
public FiveStar fivestar { get; set; }
public IEnumerator GetEnumerator()
{
return (IEnumerator)this;
}
}
public class OneStar
{
public IEnumerator GetEnumerator()
{
return (IEnumerator)this;
}
[JsonProperty("median")]
public string median { get; set; }
[JsonProperty("lowest")]
public string lowest { get; set; }
[JsonProperty("value")]
public string value { get; set; }
//public string
}
**this is the response from the web service**
{
"5 star": {
"median": "134.04",
"lowest": "83.57",
"value": "134.04"
},
"1 star": {
"median": "28.86",
"lowest": "28.86",
"value": "28.86"
},
"4 star": {
"median": "76.35",
"lowest": "36.71",
"value": "76.35"
},
"2 star": {
"median": "24.78",
"lowest": "20.42",
"value": "24.78"
},
"3 star": {
"median": "37.65",
"lowest": "20.33",
"value": "37.65"
}
}
I am getting an error stating
Unable to cast object of type 'OneStar' to type'System.Collections.IEnumerator'
Why? And how do I solve this?

First, your class is implementing, but not inheriting the IEnumerable interface, so it is still not seen as a collection.
Second, even if you inherit it, you have no collections in OneStar and nothing to enumerate.
Third, all those Json flags are not necessary as you are just redefining the defaults that are already set.
Solution
You need an additional "wrapper" class that is your collection, or just omit your custom implementation of an enumerable collection (as it does not appear from your code that you need it) and just define the property that contains the class as a collection:
public class RootobjectOne
{
public List<OneStar> onestar { get; set; }
public List<TwoStar> twostar { get; set; }
public List<ThreeStar> threestar { get; set; }
public List<FourStar> fourstar { get; set; }
public List<FiveStar> fivestar { get; set; }
}

Related

Parse (Deserialize) JSON with dynamic keys (C#)

I want to parse the JSON on the bottom. Till now I always have the static key for the variables, but in this example, the keys are always changing. Here the "58e7a898dae4c" and "591ab00722c9f" could have any value and change constantly. How can I get the value of the elements of the set to be able to reach the PreviewName value?
{
"key": "gun",
"objects": [
{
"name": "AK47",
"sets": {
"58e7a898dae4c": {
"set_id": "58e75660719a9f513d807c3a",
"preview": {
"resource": {
"preview_name": "preview.040914"
}
}
},
"591ab00722c9f": {
"set_id": "58eba618719a9fa36f881403",
"preview": {
"resource": {
"preview_name": "preview.81a54c"
}
}
}
}
}
]
}
public class Object
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("sets")]
public Dictionary<string, Set> Sets { get; set; }
}
public class Set
{
[JsonProperty("set_id")]
public string SetId { get; set; }
[JsonProperty("preview")]
public Preview Preview { get; set; }
}
public class Preview
{
[JsonProperty("resource")]
public ResourcePreview Resource { get; set; }
}
public class ResourcePreview
{
[JsonProperty("preview_name")]
public string PreviewName { get; set; }
}
var root = JsonConvert.DeserializeObject<RootObject>(json);
string previewName1 = root.Objects[0].Sets["58e7a898dae4c"].Preview.Resource.PreviewName;
string previewName2 = root.Objects[0].Sets["591ab00722c9f"].Preview.Resource.PreviewName;
you don't need to deserialize, you can parse
var jsonParsed=JObject.Parse(json);
string[] previewNames= ((JArray)jsonParsed["objects"])
.Select(v => ((JObject)v["sets"]))
.Select(i=>i.Properties().Select(y=> y.Value["preview"]["resource"])).First()
.Select(i=> (string) ((JObject)i)["preview_name"]).ToArray();
result
preview.040914
preview.81a54c

Deserialize JSON object as .NET HashSet and Lists Failed

I have this kind of Json I want to save:
"data": {
"importMannerTypeList": {
"importMannerTypeID": 5,
"importMannerTypeDesc": "a"
},
"authoritySourceList": [
{
"authoritySourceID": 1,
"authoritySourceDesc": "b"
}
],
"permitStatusList": {
"permitStatusID": 4,
"permitStatusDesc": "c"
}}
All of them set as Arrays, but because authoritySourceList is multi select and not 1 object it look like this. here is the class that Deserialize the json, importMannerTypeList and permitStatusList failed to get the data from JSON why?
public class ImportPlantSettingsResponse
{
public ImportPlantSettingsResponse()
{
ImportMannerTypeList = new List<ImportMannerType>();
AuthoritySourceList = new HashSet<AuthoritySource>();
PermitStatusList = new List<PermitStatusResponse>();
}
public virtual List<ImportMannerType> ImportMannerTypeList { get; set; }
public virtual ICollection<AuthoritySource> AuthoritySourceList { get; set; }
public virtual List<PermitStatusResponse> PermitStatusList { get; set; }
As Selim Yildiz said,ImportMannerTypeList and PermitStatusList are not lists.Here is a demo:
Model:
public class ImportPlantSettingsResponse
{
public ImportPlantSettingsResponse()
{
AuthoritySourceList = new HashSet<AuthoritySource>();
}
public virtual ImportMannerType ImportMannerTypeList { get; set; }
public virtual ICollection<AuthoritySource> AuthoritySourceList { get; set; }
public virtual PermitStatusResponse PermitStatusList { get; set; }
}
action:
public IActionResult TestImportPlantSettingsResponse([FromBody] ImportPlantSettingsResponse importPlantSettingsResponse) {
return Ok();
}
result:

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?

Deserialize nested JSON Response with RestSharp Client

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.

How to create class for JSON web service result in windows phone 7?

how can I create class for JSON web service result? This is my JSON result which i get from google api. so, how to create class and deserialization for this JSON object.
I created class to deserialization this JSON object like this,
string mapdetail = e.Result;
var djosn = new DataContractJsonSerializer(typeof(mapResult));
var mstr = new MemoryStream(Encoding.UTF8.GetBytes(mapdetail));
mapResult reslt = (mapResult)djosn.ReadObject(mstr);
mapResult class:
[DataContract]
public class mapResult
{
[DataMember]
public string status
{
get;
set;
}
[DataMember]
public IList<Resultdetail> result
{
get;
set;
}
}
So i creadet list for result details and others:
[DataContract]
public class Resultdetail
{
[DataMember]
public List<string> types
{
get;
set;
}
[DataMember]
public string formatted_address
{
get;
set;
}
[DataMember]
public List<object> address_components
{
get;
set;
}
[DataMember]
public List<Geometry> geometry
{
get;
set;
}
}
[DataContract]
public class Geometry
{
[DataMember]
public List<GeoLocation> location
{
get;
set;
}
[DataMember]
public string location_type
{
get;
set;
}
[DataMember]
public List<object> viewport
{
get;
set;
}
[DataMember]
public List<object> bounds
{
get;
set;
}
}
[DataContract]
public class GeoLocation
{
[DataMember]
public double lat
{
get;
set;
}
[DataMember]
public double lng
{
get;
set;
}
}
Now I'm getting Null reference;
There were a few issues with your DatContract classes.
I've corrected these below, commented out the original lines and added a comment about what was specifically wrong.
[DataContract]
public class mapResult
{
[DataMember]
public string status { get; set; }
[DataMember]
//public IList<Resultdetail> result { get; set; }
// Misspelt property name and use of interface rather than concrete type
public List<Resultdetail> results { get; set; }
}
[DataContract]
public class Resultdetail
{
[DataMember]
public List<string> types { get; set; }
[DataMember]
public string formatted_address { get; set; }
[DataMember]
public List<object> address_components { get; set; }
[DataMember]
//public List<Geometry> geometry { get; set; }
// Json does not contain an array/list of these
public Geometry geometry { get; set; }
}
[DataContract]
public class Geometry
{
[DataMember]
//public List<GeoLocation> location { get; set; }
// Json does not contain an array/list of these
public GeoLocation location { get; set; }
[DataMember]
public string location_type { get; set; }
[DataMember]
// public List<object> viewport { get; set; }
// Json does not contain an array/list of these
public object viewport { get; set; }
[DataMember]
//public List<object> bounds { get; set; }
// Json does not contain an array/list of these
public object bounds { get; set; }
}
The following code shows that this works:
var jsonStr = "{\"status\": \"OK\", \"results\": [ { \"types\": [ \"route\" ], \"formatted_address\": \"7th Main Rd, Koramangala, sengaluru, Karnataka 560034, India\", \"address_components\": [ { \"long_name\": \"7th Main Rd\", \"short_name\": \"7th Main Rd\", \"types\": [ \"route\" ] }, { \"long_name\": \"Koramangala\", \"short_name\": \"Koramangala\", \"types\": [ \"sublocality\", \"political\" ] }, { \"long_name\": \"Bengaluru\", \"short_name\": \"Bengaluru\", \"types\": [ \"locality\", \"political\" ] }, { \"long_name\": \"sengaluru\", \"short_name\": \"sengaluru\", \"types\": [ \"administrative_area_level_2\", \"political\" ] }, { \"long_name\": \"Karnataka\", \"short_name\": \"Karnataka\", \"types\": [ \"administrative_area_level_1\", \"political\" ] }, { \"long_name\": \"India\", \"short_name\": \"IN\", \"types\": [ \"country\", \"political\" ] }, { \"long_name\": \"560034\", \"short_name\": \"560034\", \"types\": [ \"postal_code\" ] }],\"geometry\": { \"location\":{ \"lat\": 12.9259085, \"lng\": 77.6334715 }, \"location_type\": \"GEOMETRIC_CENTER\", \"viewport\": { \"southwest\": { \"lat\": 12.9227118, \"lng\": 77.6301852 }, \"northeast\": { \"lat\": 12.929007, \"lng\": 77.6364805}}, \"bounds\": { \"southwest\": { \"lat\": 12.9247615, \"lng\": 77.6330486 },\"northeast\": { \"lat\": 12.9269574, \"lng\": 77.6336171 }}}}]}";
// If using json.net (http://json.codeplex.com/)
var des = JsonConvert.DeserializeObject<mapResult>(jsonStr);
// If using System.Runtime.Serialization.Json
var djosn = new DataContractJsonSerializer(typeof(mapResult));
var mstr = new MemoryStream(Encoding.UTF8.GetBytes(jsonStr));
des = (mapResult)djosn.ReadObject(mstr);
var latitude = des.results[0].geometry.location.lat;
var longitude = des.results[0].geometry.location.lng;
Note that my code is tested with your sample json object only and is not guaranteed to work with everything returned by the web service. You're also deserialising quite a lot to object which may be awkward to work with if you want more than just the latitude and longitude.
I note that your top-level list is called result whereas the JSON name is results btw - could it be as simple as that? Maybe the deserializer is ignoring the results value because you don't have a property of that name.
If that doesn't work... You've got 7 dereferencing operations in that statement. (4 obvious ones and 3 array indexing operations). That's an awful lot of possible failure points. I suggest you put a break point on that statement (to break before it executes) and then use the watch window to look at what results you've actually got.
(Personally I've used Json.NET in Windows Phone 7 rather than the built-in libraries, but I'm sure the latter should work too.)

Categories