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/
Related
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; }
}
I have a collection of classes set out like this:
public class Xml
{
public string version { get; set; }
public string encoding { get; set; }
}
public class Content
{
public string Expires { get; set; }
public string MaxArrivalScope { get; set; }
}
public class Trip
{
public string ETA { get; set; }
public string TripNo { get; set; }
public string WheelchairAccess { get; set; }
}
public class Destination
{
public string Name { get; set; }
public List<Trip> Trip { get; set; }
}
public class Route
{
public string RouteNo { get; set; }
public string Name { get; set; }
public Destination Destination { get; set; }
}
public class Platform
{
public string PlatformTag { get; set; }
public string Name { get; set; }
public Route Route { get; set; }
}
public class JPRoutePositionET
{
public string xmlns { get; set; }
public string xsi { get; set; }
public string schemaLocation { get; set; }
public Content Content { get; set; }
public Platform Platform { get; set; }
}
public class RootObject
{
public Xml xml { get; set; }
public JPRoutePositionET JPRoutePositionET { get; set; }
}
}
I have JSON like this:
{
"xml": {
"version": "1.0",
"encoding": "utf-8"
},
"JPRoutePositionET": {
"xmlns": "urn:connexionz-co-nz:jp",
"xsi": "http://www.w3.org/2001/XMLSchema-instance",
"schemaLocation": "urn:connexionz-co-nz:jp JourneyPlanner.xsd",
"Content": {
"Expires": "2017-04-09T15:59:31+12:00",
"MaxArrivalScope": "60"
},
"Platform": {
"PlatformTag": "2628",
"Name": "Awatea Rd near Awatea Gdns",
"Route": {
"RouteNo": "125",
"Name": "Redwood/Westlake",
"Destination": {
"Name": "Westlake & Halswell",
"Trip": [
{
"ETA": "4",
"TripNo": "4751",
"WheelchairAccess": "true"
},
{
"ETA": "32",
"TripNo": "4752",
"WheelchairAccess": "true"
}
]
}
}
}
}
}
Why is Newtonsoft not parsing correctly to the Platform class? It returns null. Will I need to format the JSON to cut out all the other information I don't want? Or is it something I am missing?
Fabio's Comment of
var result = Newtonsoft.Json.JsonConvert.DeserializeObject<RootObject>(jsonString);
Worked.
But now when I get JSON like pastebin.com/pebp178s I can't seem to use Json2CSharp to get the classes I'd need as it doesn't make Destination a List, it also changes Trip to an Object instead of a class. Which is really weird. It just throws an error saying the JSON can't be parsed.
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.
I am trying to deserealize json:
Classes is generated by json2sharp
But it throws exception:
Element ": Data" contains data from a data type that maps to the name
"http://schemas.datacontract.org/2004/07/TMSoft.CryptoDoc.Gu45:Gu45".
The deserializer is no information of any type, are matched with the
same name. Use DataContractResolver or add type that matches "Gu45",
the list of known types, such as using KnownTypeAttribute attribute or
by adding it to the list of known types passed to
DataContractSerializer.
How to fix it?
namespace json
{
class Program
{
static void Main(string[] args)
{
string json = System.IO.File.ReadAllText(#"D:\Json.txt");
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(RootObject));
var account = serializer.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(json)));
}
}
public class Branch
{
public string Code { get; set; }
public string Name { get; set; }
}
public class Direction
{
public object Code { get; set; }
public string Name { get; set; }
}
public class Org
{
public string Code { get; set; }
public string Name { get; set; }
}
public class Wagon
{
public string Comment { get; set; }
public object NoteTimeString { get; set; }
public string Number { get; set; }
public string OwnerCode { get; set; }
public string StateString { get; set; }
}
public class Data
{
public string __type { get; set; }
public Branch Branch { get; set; }
public string DeliveryTimeString { get; set; }
public Direction Direction { get; set; }
public string EsrCode { get; set; }
public int GU45Type { get; set; }
public object ManeuverTime { get; set; }
public string Number { get; set; }
public Org Org { get; set; }
public object ParkName { get; set; }
public object ParkNum { get; set; }
public string RailwayName { get; set; }
public string RegistrationDateTimeString { get; set; }
public object Span { get; set; }
public string StationName { get; set; }
public string TakingTimeString { get; set; }
public object TrackNum { get; set; }
public object TrackNumAddition { get; set; }
public object WagonNote { get; set; }
public List<Wagon> Wagons { get; set; }
}
public class Body
{
public Data Data { get; set; }
public List<int> Signature { get; set; }
}
public class RootObject
{
public Body Body { get; set; }
public int Revision { get; set; }
public int State { get; set; }
public string StateDate { get; set; }
public string WosId { get; set; }
}
}
Json.txt:
{
"Body": {
"Data": {
"__type": "Gu45:#TMSoft.CryptoDoc.Gu45",
"Branch": {
"Code": "9898",
"Name": "Place"
},
"DeliveryTimeString": "07.03.2014 10:00:00",
"Direction": {
"Code": null,
"Name": "Test"
},
"EsrCode": "320007",
"GU45Type": 2,
"ManeuverTime": null,
"Number": "1",
"Org": {
"Code": "1860",
"Name": "Test"
},
"ParkName": null,
"ParkNum": null,
"RailwayName": "Test",
"RegistrationDateTimeString": "07.03.2014",
"Span": null,
"StationName": "Test",
"TakingTimeString": "07.03.2014 12:00:00",
"TrackNum": null,
"TrackNumAddition": null,
"WagonNote": null,
"Wagons": [
{
"Comment": "РЕМТ",
"NoteTimeString": null,
"Number": "44916989",
"OwnerCode": "22",
"StateString": "0"
}
]
},
"Signature": [
48,
106
]
},
"Revision": 1966,
"State": 2,
"StateDate": "2014-03-07T12:48:03Z",
"WosId": "15805729"
}
I had similar experience in my previous projects with DataContractJsonSerializer. it seems that "__type" field has a special meaning for DataContractJsonSerializer.
This is one of the main reasons that I use Json.net
it matters only if it's the first property in the object but if it has any other positions it works and exceptions is not thrown. you can try it but changing __type position below the branch property in Json.txt. I don't know if it's the case and you can find a workaround.
I haven't tried this solution but it worth to give it a try:
hope it helps
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 :