Newtonsoft.Json.JsonReaderException: 'Unexpected character encountered while parsing value - c#

I have a Json Model Schema from a third party API that looks like this:
{
"Entries": [
{
"Id": "",
"RowId": 0,
"FormId": "",
"FormExternalId": "",
"FormVersion": 0,
"DeviceId": "",
"UserFirstName": "",
"UserLastName": "",
"UserEmail": "",
"UserExternalId": "",
"Latitude": 0,
"Longitude": 0,
"StartTime": "Date",
"CompleteTime": "Date",
"ReceivedTime": "Date",
"AnswerFormat": "",
"Answers": [
{
"Name": "",
"Type": "",
"Value": "",
"Answers": [
"Answer_GET_"
]
}
],
"AnswersFlat": "Array[AnswerSet]",
"AnswersFlatXml": "XML",
"AnswersRawXml": "XML",
"AnswersRawJson": "JSON",
"TaskId": "",
"DSRowId": "",
"MediaAsUrl": false,
"Fields": "",
"PurgeDays": 0,
"CompanyId": 0
}
],
"TotalRows": 0,
"ResponseStatus": {
"ErrorCode": "",
"Message": "",
"Errors": [
{
"ErrorCode": "",
"FieldName": "",
"Message": ""
}
]
}
}
I made a class for this in Visual Studio that looks like this:
class form_results
{
public class Rootobject
{
public Entry[] Entries { get; set; }
public int TotalRows { get; set; }
public Responsestatus ResponseStatus { get; set; }
}
public class Responsestatus
{
public string ErrorCode { get; set; }
public string Message { get; set; }
public Error[] Errors { get; set; }
}
public class Error
{
public string ErrorCode { get; set; }
public string FieldName { get; set; }
public string Message { get; set; }
}
public class Entry
{
public string Id { get; set; }
public int RowId { get; set; }
public string FormId { get; set; }
public string FormExternalId { get; set; }
public int FormVersion { get; set; }
public string DeviceId { get; set; }
public string UserFirstName { get; set; }
public string UserLastName { get; set; }
public string UserEmail { get; set; }
public string UserExternalId { get; set; }
public float Latitude { get; set; }
public float Longitude { get; set; }
public string StartTime { get; set; }
public string CompleteTime { get; set; }
public string ReceivedTime { get; set; }
public string AnswerFormat { get; set; }
public Answer[] Answers { get; set; }
public string AnswersFlat { get; set; }
public string AnswersFlatXml { get; set; }
public string AnswersRawXml { get; set; }
public string AnswersRawJson { get; set; }
public string TaskId { get; set; }
public string DSRowId { get; set; }
public bool MediaAsUrl { get; set; }
public string Fields { get; set; }
public int PurgeDays { get; set; }
public int CompanyId { get; set; }
}
public class Answer
{
public string Name { get; set; }
public string Type { get; set; }
public string Value { get; set; }
public string[] Answers { get; set; }
}
}
When I try to deserialize the json with the following command:
var parsedJson = JsonConvert.DeserializeObject<form_results.Rootobject>(json);
I'm geting the error "Newtonsoft.Json.JsonReaderException: 'Unexpected character encountered while parsing value: {. Path 'Entries[0].Answers[0].Answers', line 25, position 25.'"
That part of the Json string looks like this:
{... more json results...
"AnswerFormat": "Rich",
"Answers": [{
"Name": "Page 1",
"Type": "Group",
"Answers": [{
"Name": "Value 1",
"Type": "SelectOne"
},
{
"Name": "Value 2",
"Type": "SelectOne"
}
]
}]
}
]
The Json is valid, so that is not the problem. As far as I can see the problem occurs at the array section of the Json file.
Also tried var parsedJson = JsonConvert.DeserializeObject <List<form_results.Rootobject>>(json); but gave also an error.
What I want is the results (answers) from the Answers array.

Your Answer class is declared like this
public class Answer
{
public string Name { get; set; }
public string Type { get; set; }
public string Value { get; set; }
public string[] Answers { get; set; }
}
This includes an array of string called Answers
But in your JSON, this array is an array of objects (Extract below)
"Answers": [{
"Name": "Value 1",
"Type": "SelectOne"
},
{
"Name": "Value 2",
"Type": "SelectOne"
}
]
So you need to change your class to match this JSON. Maybe like this
public class Answer
{
public string Name { get; set; }
public string Type { get; set; }
public string Value { get; set; }
public SubAnswer[] Answers { get; set; }
}
public class SubAnswer
{
public string Name { get; set; }
public string Type { get; set; }
}
Or you could maybe use the Composite pattern, if you want Answer and SubAnswer to be the same.

It looks like the class answers can contain further answers thats why you can modify your Answer class like following:
public class Answer
{
public string Name { get; set; }
public string Type { get; set; }
public string Value { get; set; }
public List<Answer> Answers { get; set; }
}

Related

Deserializing result of steam storefront api using RestSharp always returns null

I've been trying to use the steam storefront api http://store.steampowered.com/api/.
The problem is that when I feed the result of the api to RestSharp, the data is always null.
So my question is how do I get the Rest call deserialized?
First, this is what you would be expecting when calling appdetails?appids=[appid]
{
"3400": {
"success": true,
"data": {
"type": "game",
"name": "Hammer Heads Deluxe",
"steam_appid": 3400,
"required_age": 0,
"is_free": false,
"detailed_description": "",
"about_the_game": "",
"short_description": "",
"supported_languages": "English",
"header_image": "http:\/\/cdn.akamai.steamstatic.com\/steam\/apps\/3400\/header.jpg?t=1447350883",
"website": null,
"pc_requirements": {
"minimum": "<p><strong>Minimum Requirements:<\/strong> Windows 98\/ME\/2000\/XP, 128 MB RAM, 500MHz or faster, DirectX: 7.0<\/p>"
},
"mac_requirements": [
],
"linux_requirements": [
],
"developers": [
"PopCap Games, Inc."
],
"publishers": [
"PopCap Games, Inc."
],
"demos": [
{
"appid": 3402,
"description": ""
}
],
"price_overview": {
"currency": "USD",
"initial": 499,
"final": 499,
"discount_percent": 0
},
"packages": [
135
],
"package_groups": [
{
"name": "default",
"title": "Buy Hammer Heads Deluxe",
"description": "",
"selection_text": "Select a purchase option",
"save_text": "",
"display_type": 0,
"is_recurring_subscription": "false",
"subs": [
{
"packageid": 135,
"percent_savings_text": "",
"percent_savings": 0,
"option_text": "Hammer Heads Deluxe - $4.99",
"option_description": "",
"can_get_free_license": "0",
"is_free_license": false,
"price_in_cents_with_discount": 499
}
]
}
],
"platforms": {
"windows": true,
"mac": false,
"linux": false
},
"categories": [
{
"id": 2,
"description": "Single-player"
}
],
"genres": [
{
"id": "4",
"description": "Casual"
}
],
"screenshots": [
{
"id": 0,
"path_thumbnail": "http:\/\/cdn.akamai.steamstatic.com\/steam\/apps\/3400\/0000000564.600x338.jpg?t=1447350883",
"path_full": "http:\/\/cdn.akamai.steamstatic.com\/steam\/apps\/3400\/0000000564.1920x1080.jpg?t=1447350883"
},
{
"id": 1,
"path_thumbnail": "http:\/\/cdn.akamai.steamstatic.com\/steam\/apps\/3400\/0000000565.600x338.jpg?t=1447350883",
"path_full": "http:\/\/cdn.akamai.steamstatic.com\/steam\/apps\/3400\/0000000565.1920x1080.jpg?t=1447350883"
},
{
"id": 2,
"path_thumbnail": "http:\/\/cdn.akamai.steamstatic.com\/steam\/apps\/3400\/0000000566.600x338.jpg?t=1447350883",
"path_full": "http:\/\/cdn.akamai.steamstatic.com\/steam\/apps\/3400\/0000000566.1920x1080.jpg?t=1447350883"
},
{
"id": 3,
"path_thumbnail": "http:\/\/cdn.akamai.steamstatic.com\/steam\/apps\/3400\/0000000567.600x338.jpg?t=1447350883",
"path_full": "http:\/\/cdn.akamai.steamstatic.com\/steam\/apps\/3400\/0000000567.1920x1080.jpg?t=1447350883"
},
{
"id": 4,
"path_thumbnail": "http:\/\/cdn.akamai.steamstatic.com\/steam\/apps\/3400\/0000000568.600x338.jpg?t=1447350883",
"path_full": "http:\/\/cdn.akamai.steamstatic.com\/steam\/apps\/3400\/0000000568.1920x1080.jpg?t=1447350883"
}
],
"release_date": {
"coming_soon": false,
"date": "Aug 30, 2006"
},
"support_info": {
"url": "",
"email": ""
},
"background": "http:\/\/cdn.akamai.steamstatic.com\/steam\/apps\/3400\/page_bg_generated_v6b.jpg?t=1447350883"
}
}
}
That is the json block returned for accessing appid 3400. Note how it's appid is located inside of file itself.
In order to generate classes for this, I made a formatted version of that based off the unofficial storefront api documentation. Then I used that to generate the container classes shown below.
public class Appid
{
public bool success { get; set; }
public Data data { get; set; }
}
public class Data
{
public string type { get; set; }
public string name { get; set; }
public int steam_appid { get; set; }
public int required_age { get; set; }
public int[] dlc { get; set; }
public string detailed_description { get; set; }
public string about_the_game { get; set; }
public Fullgame fullgame { get; set; }
public string supported_languages { get; set; }
public string header_image { get; set; }
public string website { get; set; }
public Pc_Requirements pc_requirements { get; set; }
public Mac_Requirements mac_requirements { get; set; }
public Linux_Requirements linux_requirements { get; set; }
public string[] developers { get; set; }
public Demos demos { get; set; }
public Price_Overview price_overview { get; set; }
public int[] packages { get; set; }
public Package_Groups[] package_groups { get; set; }
public Platforms platforms { get; set; }
public Metacritic metacritic { get; set; }
public Category[] categories { get; set; }
public Screenshot[] screenshots { get; set; }
public Movie[] movies { get; set; }
public Recommendations recommendations { get; set; }
public Achievements achievements { get; set; }
public Release_Date release_date { get; set; }
}
public class Fullgame
{
public int appid { get; set; }
public string name { get; set; }
}
public class Pc_Requirements
{
public string minimum { get; set; }
public string recommended { get; set; }
}
public class Mac_Requirements
{
public string minimum { get; set; }
public string recommended { get; set; }
}
public class Linux_Requirements
{
public string minimum { get; set; }
public string recommended { get; set; }
}
public class Demos
{
public int appid { get; set; }
public string description { get; set; }
}
public class Price_Overview
{
public string currency { get; set; }
public int initial { get; set; }
public int final { get; set; }
public int discount_precent { get; set; }
}
public class Platforms
{
public bool windows { get; set; }
public bool mac { get; set; }
public bool linux { get; set; }
}
public class Metacritic
{
public int score { get; set; }
public string url { get; set; }
}
public class Recommendations
{
public int total { get; set; }
}
public class Achievements
{
public int total { get; set; }
public Highlighted[] highlighted { get; set; }
}
public class Highlighted
{
public string name { get; set; }
public string path { get; set; }
}
public class Release_Date
{
public bool coming_soon { get; set; }
public string date { get; set; }
}
public class Package_Groups
{
public string name { get; set; }
public string title { get; set; }
public string description { get; set; }
public string selection_text { get; set; }
public string save_text { get; set; }
public int display_type { get; set; }
public string is_recurring_subscription { get; set; }
public Sub[] subs { get; set; }
}
public class Sub
{
public int packageid { get; set; }
public string percent_savings_text { get; set; }
public int percent_savings { get; set; }
public string option_text { get; set; }
public string option_description { get; set; }
}
public class Category
{
public int id { get; set; }
public string description { get; set; }
}
public class Screenshot
{
public int id { get; set; }
public string path_thumbnail { get; set; }
public string path_full { get; set; }
}
public class Movie
{
public int id { get; set; }
public string name { get; set; }
public string thumbnail { get; set; }
public Webm webm { get; set; }
}
public class Webm
{
public string _480 { get; set; }
public string max { get; set; }
}
Now onto the code, the function takes in a long and should return a Data object. However, instead of deserializing, it returns a null. I have checked to make sure the json is actually getting to the code. It is coming in fine.
//Steam rest stuff always returns with one object.
//This it to keep me writing 10 classes that do essentially the same thing
//And before you ask, yes, I have tried doing this without this class.
//Still didn't work.
public class RootObject<T>
{
public T response { get; set; }
}
public static Data GetGameData(long appid)
{
//Only thing different about this function except for the fact that it's also static
RestClient storeClient = new RestClient("http://store.steampowered.com/api/");
RestRequest restReq = new RestRequest("appdetails/", Method.GET);
restReq.AddParameter("appids", appid);
restReq.RequestFormat = DataFormat.Json;
restReq.OnBeforeDeserialization = resp =>
{
//This was done as an attempt to fix it.
//It makes the appid's in the content into {"appId":{
//EX: {"400":{ -> {"appId":{
resp.Content = Regex.Replace(resp.Content, "{\"\\d+\":{", "{\"appId\":{");
};
IRestResponse<RootObject<Appid>> response = storeClient.Execute<RootObject<Appid>>(restReq);
Appid trueRes = response.Data.response;
return trueRes.data;
}
Quick note, the function was altered but only to work in a static context.
The edit was noted in code.
Things I've tried
Explicitly specifying that the file is a json file.
Changing the appid class names to a common class name.
Using Json.Net as the deserializer.
Removing the "success": true item.
Using [DeserializeAs(Name = "appId")] in the appid class.
Using a non generic version of RootObject
Tried using Dictionary<string, Appid> instead of RootObject<Appid>
Edit:
For some extra information I did some testing on the methods.
I remade the object carrying classes using appid 4000 and put that into json to sharp converter. Then I wrote a small bit of code that tested if the data was null.
static void TestIfFetched(long appid)
{
Console.Write($"{appid}\t:");
Data data = GetGameData(appid);
if (data == null)
{
Console.WriteLine("Failed to get data.");
}
else
{
Console.WriteLine("Data fetched successfully.");
}
}
The result was this when testing 4000 and 400.
4000 :Failed to get data.
400 :Failed to get data.
So it seems even using data specifically designed for that game, it still fails to parse.
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
RestClient storeClient = new RestClient("https://store.steampowered.com/api/");
RestRequest restReq = new RestRequest("appdetails/", Method.GET);
restReq.AddParameter("appids", appid);
restReq.RequestFormat = DataFormat.Json;
var response = storeClient.Execute<dynamic>(restReq);
JObject jObject = JObject.Parse(response.Content);
var details = jObject[appid].Value<JObject>().ToObject<Appid>();
The above worked for me. The JObject allows you to pass the appid as a parameter and then parse your object from there.

Deserialize complex JSON result

I am automating an API. I would like to deserialize the JSON response I get but I can't figure out how to do it. This is the JSON I get as response:
{
"class": [
"Paged-Collection",
"Products"
],
"properties": {
"defaultPageSize": 10,
"skip": null,
"top": 10,
"totalRows": 2
},
"entities": [
{
"class": [
"Product"
],
"rel": [],
"properties": {
"Supplier": "Supplier1",
"Currency": "USD",
"ProductCode": "SomeCode1",
"price": 2
}
},
{
"class": [
"Product"
],
"rel": [],
"properties": {
"Supplier": "Supplier2",
"Currency": "USD",
"ProductCode": "SomeCode2",
"price": 73
}
},
],
"links": [
{
"rel": [
"self"
],
"href": "http://localhost...",
"method": "GET",
"title": null,
"type": null
}
]
}
from what I've seen in other examples the deserialization boils down to figuring out the exact data strucutre (Not sure though if this what it is) however I made several attempts (not just rushing to SO for answer), so this is my last try:
The structure as I see it:
public class Data
{
List<string> #class { get; set; }
Dictionary<string, MetaData> properties { get; set; }
List<entities> entities { get; set; }
List<LinkFeed> links { get; set; }
}
public class MetaData
{
public int defaultPageSize { get; set; }
public string skip { get; set; }
public int top { get; set; }
public int totalRows { get; set; }
}
public class entities
{
public List<string> #class { get; set; }
public List<string> rel { get; set; }
public properties property { get; set; }
}
public class properties
{
public string Supplier { get; set; }
public string Currency { get; set; }
public string ProductCode { get; set; }
public string price { get; set; }
public double Price { get; set; }
}
public class LinkFeed
{
public List<string> rel { get; set; }
public string href { get; set; }
public string method { get; set; }
public string title { get; set; }
public string type { get; set; }
}
And the actual deserialization using Newtonsoft.Json :
var result = JsonConvert.DeserializeObject<Data>(data);
And everything is Null..
Actually the data that I'm really interested in is that under "entities" but I don't know if extracting only that will be actually easier or more difficult.
This is your structure:
public class Rootobject {
public string[] _class { get; set; }
public Properties properties { get; set; }
public Entity[] entities { get; set; }
public Link[] links { get; set; }
}
public class Properties {
public int defaultPageSize { get; set; }
public object skip { get; set; }
public int top { get; set; }
public int totalRows { get; set; }
}
public class Entity {
public string[] _class { get; set; }
public object[] rel { get; set; }
public Properties1 properties { get; set; }
}
public class Properties1 {
public string Supplier { get; set; }
public string Currency { get; set; }
public string ProductCode { get; set; }
public int price { get; set; }
}
public class Link {
public string[] rel { get; set; }
public string href { get; set; }
public string method { get; set; }
public object title { get; set; }
public object type { get; set; }
}
So you will do this:
var result = JsonConvert.DeserializeObject<Rootobject>(data);
I would rename the class Properties to another name because it will clash with the Properties class of the assembly. This will give you headaches so just to be safe call it something else.
Also if you do not like some of the property names in the above classes, I mean I do not like it because it does not follow .NET naming conventions, then you can do this:
public class Rootobject {
[JsonProperty( "class" )]
public string[] MyClass { get; set; }
// ... other properties
}
Obviously calling it MyClass is just an example, so give it a name that reflects the business domain.

Json DeserializeObject return null - what i am doing wrong?

Here is the call to DeserializeObject:
listrootobject obj = JsonConvert.DeserializeObject<listrootobject>(json);
Here is Json .
{
"so:MemberProfileDataSet": {
"#xmlns:moso": "http://schema.socloud.com/1/MemberProfileDataSet.xsd",
"Member": {
"#xmlns": "http://schema.socloud.com/1/MemberProfileDataSet.xsd",
"PartyId": "63",
"PartyTypeName": "Employee",
"RoleId": "1310",
"BusinessUnitCode": "95",
"CardId": null,
"PostalContact": {
"PartyId": "63",
"TypeName": "Mailing Address",
"Address1": "100 Main Ave",
"Address2": null,
"Address3": null,
"City": "Arlington",
"State": "VA",
"PostalCode": "22206"
},
"PhoneContact": [{
"PartyId": "63",
"TypeName": "Cell",
"CountryCode": "1",
"Telephone": "(555) 555-5555",
"AdditionalData": null,
"TextMessageOK": "false"
}, {
"PartyId": "63",
"TypeName": "Home",
"CountryCode": "1",
"Telephone": null,
"AdditionalData": null,
"TextMessageOK": "false"
}],
"Property": [{
"PartyId": "63",
"Name": "First Name",
"Value": "Katie"
}, {
"PartyId": "63",
"Name": "Last Name",
"Value": "Rodriguez"
}, {
"PartyId": "63",
"Name": "Payroll ID",
"Value": null
}, {
"PartyId": "63",
"Name": "Lookup Initials",
"Value": null
}, {
"PartyId": "63",
"Name": "Date of Birth",
"Value": null
}, {
"PartyId": "63",
"Name": "Hire Date",
"Value": null
}, {
"PartyId": "63",
"Name": "Termination Date",
"Value": null
}, {
"PartyId": "63",
"Name": "Gender",
"Value": null
}]
}
}
}
Here is C# Class
public class PostalContact
{
public string PartyId { get; set; }
public string TypeName { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Address3 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
}
public class EmailContact
{
public string PartyId { get; set; }
public string TypeName { get; set; }
public string EmailAddress { get; set; }
public string EmailOptOut { get; set; }
}
public class PhoneContact
{
public string PartyId { get; set; }
public string TypeName { get; set; }
public string CountryCode { get; set; }
public string Telephone { get; set; }
public string AdditionalData { get; set; }
public string TextMessageOK { get; set; }
}
public class Property
{
public string PartyId { get; set; }
public string Name { get; set; }
public string Value { get; set; }
}
//public class rootobject
//{
// public List<Member> Members { get; set; }
//}
public class Member
{
public string PartyId { get; set; }
public string PartyTypeName { get; set; }
public string RoleId { get; set; }
public string BusinessUnitCode { get; set; }
public string CardId { get; set; }
public PostalContact PostalContact { get; set; }
public EmailContact EmailContact { get; set; }
public List<PhoneContact> PhoneContact { get; set; }
public List<Property> Property { get; set; }
public string _xmlns { get; set; }
}
public class MemberProfileDataSet
{
public Member Member { get; set; }
public string __invalid_name___xmlns_moso { get; set; }
public string __prefix { get; set; }
}
public class listrootobject
{
public List<MemberProfileDataSet> rootobjects { get; set; }
}
public class rootobject
{
public MemberProfileDataSet MemberProfileDataSet { get; set; }
}
Use http://json2csharp.com/ to generate and write your C# classes as the generated classes from the website. Lastly you parse the rootObject as below.
But you have a problem because the property names it generates are invalid in C# and you cannot create a C# class with those names. But the names must match to de-serialize. So you need to remove the invalid characters or re-name them to meet the C# CLR naming requirements.Then create a C# class of the properly formatted string. After which you can de-serialized.
For instance I generated C# object from the original string and I had a property name as
public SoMemberProfileDataSet __invalid_name__so:MemberProfileDataSet { get; set; }
This is invalid in C# but you would need to format this in the string to something valid e.g.
public SoMemberProfileDataSet MemberProfileDataSet { get; set; }
by renaming the json string or getting the properties you want from the string and re-constructing the json properly before de serializing.
Show me the code
As an example, I have combined strings between colons and removed the # symbol so that I created a valid C# object. And it de-seralizes. Please see changes in the json string below. So please format your json string and you will have it.
string json = "{\"soMemberProfileDataSet\": {\"xmlnsmoso\": \"http://schema.socloud.com/1/MemberProfileDataSet.xsd\",\"Member\": {\"xmlns\": \"http://schema.socloud.com/1/MemberProfileDataSet.xsd\",\"PartyId\": \"63\",\"PartyTypeName\": \"Employee\",\"RoleId\": \"1310\",\"BusinessUnitCode\": \"95\",\"CardId\": null,\"PostalContact\": {\"PartyId\": \"63\",\"TypeName\": \"Mailing Address\",\"Address1\": \"100 Main Ave\",\"Address2\": null,\"Address3\": null,\"City\": \"Arlington\",\"State\": \"VA\",\"PostalCode\": \"22206\"},\"PhoneContact\": [{\"PartyId\": \"63\",\"TypeName\": \"Cell\",\"CountryCode\": \"1\",\"Telephone\": \"(555) 555-5555\",\"AdditionalData\": null,\"TextMessageOK\": \"false\"}, {\"PartyId\": \"63\",\"TypeName\": \"Home\",\"CountryCode\": \"1\",\"Telephone\": null,\"AdditionalData\": null,\"TextMessageOK\": \"false\"}],\"Property\": [{\"PartyId\": \"63\",\"Name\": \"First Name\",\"Value\": \"Katie\"}, {\"PartyId\": \"63\",\"Name\": \"Last Name\",\"Value\": \"Rodriguez\"}, {\"PartyId\": \"63\",\"Name\": \"Payroll ID\",\"Value\": null}, {\"PartyId\": \"63\",\"Name\": \"Lookup Initials\",\"Value\": null}, {\"PartyId\": \"63\",\"Name\": \"Date of Birth\",\"Value\": null}, {\"PartyId\": \"63\",\"Name\": \"Hire Date\",\"Value\": null}, {\"PartyId\": \"63\",\"Name\": \"Termination Date\",\"Value\": null}, {\"PartyId\": \"63\",\"Name\": \"Gender\",\"Value\": null}]}}}";
var listrootobject = JsonConvert.DeserializeObject<RootObject>(json);
Your class should now look like as below, no more invalid property names after formatting
public class PostalContact
{
public string PartyId { get; set; }
public string TypeName { get; set; }
public string Address1 { get; set; }
public object Address2 { get; set; }
public object Address3 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
}
public class PhoneContact
{
public string PartyId { get; set; }
public string TypeName { get; set; }
public string CountryCode { get; set; }
public string Telephone { get; set; }
public object AdditionalData { get; set; }
public string TextMessageOK { get; set; }
}
public class Property
{
public string PartyId { get; set; }
public string Name { get; set; }
public string Value { get; set; }
}
public class Member
{
public string xmlns { get; set; }
public string PartyId { get; set; }
public string PartyTypeName { get; set; }
public string RoleId { get; set; }
public string BusinessUnitCode { get; set; }
public object CardId { get; set; }
public PostalContact PostalContact { get; set; }
public List<PhoneContact> PhoneContact { get; set; }
public List<Property> Property { get; set; }
}
public class SoMemberProfileDataSet
{
public string xmlnsmoso { get; set; }
public Member Member { get; set; }
}
public class RootObject
{
public SoMemberProfileDataSet soMemberProfileDataSet { get; set; }
}

Collection+JSON deserialization into object

I'm having a problem deserializing Collection+JSON(http://amundsen.com/media-types/collection/format/) into an object using C# and asp.net
JSON format:
{
"collection": {
"version": "1.0",
"href": "http://www.example.com/api/",
"links":
[{
"href": "http://example.com/api/issues",
"rel": "issuesLink",
"name": "issuesLink",
"render": "link",
"prompt": "All issues ordered by number"
}],
"queries":
[{
"href": "https:\/\/example.com\/api\/search\/{field}\/{value}",
"rel": "searchByField",
"name": "FieldSearch",
"prompt": "Search by field",
"data":
[{
"name": "name",
"value": "field"
},
{
"name": "value",
"value": ""
}]
}]
}
}
I have no problems with using (or not using) JSON.net but haven't been able to get it to deserialize properly either way. I have the JSON
public class FPResponse
{
[JsonProperty("collection")]
//I have tried using List<string> too
// public Billboard collection executes the code but returns null for o
public string collection { get; set; }
}
public class Billboard
{
[JsonProperty("version")]
public string version { get; set; }
[JsonProperty("href")]
public string href { get; set; }
[JsonProperty("links")]
public IList<LinkSet> links { get; set; }
}
using (var reader = new StreamReader(dataStream))
{
string rtn = reader.ReadToEnd(); //has the JSON string
var o = JsonConvert.DeserializeObject<FPResponse>(rtn);
}
THE ERROR using JSON.NET: Additional information: Error reading string. Unexpected token: StartObject. Path 'collection', line 1, position 15.
Thanks for your help...
collection is not a string
Your declaration should be as:
public class Link
{
public string href { get; set; }
public string rel { get; set; }
public string name { get; set; }
public string render { get; set; }
public string prompt { get; set; }
}
public class Datum
{
public string name { get; set; }
public string value { get; set; }
}
public class Query
{
public string href { get; set; }
public string rel { get; set; }
public string name { get; set; }
public string prompt { get; set; }
public List<Datum> data { get; set; }
}
public class Collection
{
public string version { get; set; }
public string href { get; set; }
public List<Link> links { get; set; }
public List<Query> queries { get; set; }
}
public class FPResponse
{
public Collection collection { get; set; }
}
You may want to visit that site http://json2csharp.com/

Get information from a json string?

I have received a json string and i need help mapping that to an object
currently i am using:
string request = webClient.DownloadString(url);
which returns a json string of invoices:
"{\"invoices\":[
{\"url\":\"https://api.freeagent.com/v2/invoices/0000001\",\"contact\":\"https://api.freeagent.com/v2/contacts/000001\",\"dated_on\":\"2010-10-29\",\"due_on\":\"2010-11-28\",\"reference\":\"0001\",\"currency\":\"GBP\",\"exchange_rate\":\"1.0\",\"net_value\":\"60.0\",\"sales_tax_value\":\"68.0\",\"total_value\":\"528.0\",\"paid_value\":\"528.0\",\"due_value\":\"0.0\",\"status\":\"Paid\",\"omit_header\":false,\"payment_terms_in_days\":30,\"paid_on\":\"2011-11-14\"},{\"url\":\"https://api.freeagent.com/v2/invoices/0000002\",\"contact\":\"https://api.freeagent.com/v2/contacts/000002\",\"dated_on\":\"2010-11-19\",\"due_on\":\"2010-12-19\",\"reference\":\"0002\",\"currency\":\"GBP\",\"exchange_rate\":\"1.0\",\"net_value\":\"80.0\",\"sales_tax_value\":\"6.5\",\"total_value\":\"326.5\",\"paid_value\":\"650.0\",\"due_value\":\"76.5\",\"status\":\"Overdue\",\"comments\":\"Work\",\"omit_header\":false,\"payment_terms_in_days\":30}]}"
I have an invoice class:
public class Invoices
{
public string url { get; set; }
public string project { get; set; } //--
public string contact { get; set; } //--
public string dated_on { get; set; } //--
public string due_on { get; set; } //--
public string paid_on { get; set; }
public string reference { get; set; } //--
public string currency { get; set; } //--
public string exchange_rate { get; set; } //--
public string net_value { get; set; }
public string sales_tax_value { get; set; }
public string total_value { get; set; }
public string paid_value { get; set; }
public string due_value { get; set; }
public string discount_percent { get; set; }
public string status { get; set; }
public string comments { get; set; } //--
public string omit_header { get; set; }
public string payment_terms_in_days { get; set; } //--
public string ec_status { get; set; } //need to add fields
public string written_off_date { get; set; }
}
Different invoices can return different information which is why there is a lot of values in the class that may not be in the json string.
I have tried these approaches but keep getting errors:
List<Invoices> list = JsonConvert.DeserializeObject<List<Invoices>>(request);
Dictionary<string, string> values = JsonConvert.DeserializeObject<Dictionary<string, string>>(request);
Could someone show me how to get the information shown in the string out?
Edit:
I have also tried:
var info = JsonConvert.DeserializeObject(request);
And that return this as a jObect
{
"invoices": [
{
"url": "https://api.freeagent.com/v2/invoices/000000",
"contact": "https://api.freeagent.com/v2/contacts/000000",
"dated_on": "2010-10-29",
"due_on": "2010-11-28",
"reference": "0000",
"currency": "GBP",
"exchange_rate": "1.0",
"net_value": "960.0",
"sales_tax_value": "568.0",
"total_value": "528.0",
"paid_value": "528.0",
"due_value": "0.0",
"status": "Paid",
"omit_header": false,
"payment_terms_in_days": 30,
"paid_on": "2011-11-14"
},
{
"url": "https://api.freeagent.com/v2/invoices/000000",
"contact": "https://api.freeagent.com/v2/contacts/000000",
"dated_on": "2010-11-19",
"due_on": "2010-12-19",
"reference": "0000",
"currency": "GBP",
"exchange_rate": "1.0",
"net_value": "980.0",
"sales_tax_value": "46.5",
"total_value": "326.5",
"paid_value": "650.0",
"due_value": "76.5",
"status": "Overdue",
"comments": "Work",
"omit_header": false,
"payment_terms_in_days": 30
}
}
The classes (as for the Json u posted) should look like this:
public class Invoice
{
public string url { get; set; }
public string contact { get; set; }
public string dated_on { get; set; }
public string due_on { get; set; }
public string reference { get; set; }
public string currency { get; set; }
public string exchange_rate { get; set; }
public string net_value { get; set; }
public string sales_tax_value { get; set; }
public string total_value { get; set; }
public string paid_value { get; set; }
public string due_value { get; set; }
public string status { get; set; }
public bool omit_header { get; set; }
public int payment_terms_in_days { get; set; }
public string paid_on { get; set; }
public string comments { get; set; }
}
public class RootObject
{
public List<Invoice> invoices { get; set; }
}
And:
RootObject list = JsonConvert.DeserializeObject<RootObject>(request);
The RootObject object contains a list of invoices
Json: (there is a ] missing on your version, near the end of the Json to close the array)
{
"invoices": [
{
"url": "https://api.freeagent.com/v2/invoices/000000",
"contact": "https://api.freeagent.com/v2/contacts/000000",
"dated_on": "2010-10-29",
"due_on": "2010-11-28",
"reference": "0000",
"currency": "GBP",
"exchange_rate": "1.0",
"net_value": "960.0",
"sales_tax_value": "568.0",
"total_value": "528.0",
"paid_value": "528.0",
"due_value": "0.0",
"status": "Paid",
"omit_header": false,
"payment_terms_in_days": 30,
"paid_on": "2011-11-14"
},
{
"url": "https://api.freeagent.com/v2/invoices/000000",
"contact": "https://api.freeagent.com/v2/contacts/000000",
"dated_on": "2010-11-19",
"due_on": "2010-12-19",
"reference": "0000",
"currency": "GBP",
"exchange_rate": "1.0",
"net_value": "980.0",
"sales_tax_value": "46.5",
"total_value": "326.5",
"paid_value": "650.0",
"due_value": "76.5",
"status": "Overdue",
"comments": "Work",
"omit_header": false,
"payment_terms_in_days": 30
}]
}
Could someone show me how to get the information shown in the string
out?
You can do this (dynamic):
JavaScriptSerializer oSerializer = new JavaScriptSerializer();
dynamic lst = oSerializer.Deserialize<dynamic>(request );
Console.WriteLine(lst["invoices"][0]["due_on"]); <--put here whatever you want.
Here for example , I read the value of the first item in array :

Categories

Resources