JSON.NET won't deserialize into my object, throws an exception - c#

My JSON (myString) looks like this:
"http://d.opencalais.com/dochash-1/0701d73f-2f99-39e1-8c29-e61ee8bf3238/cat/1":
{
"_typeGroup": "topics",
"category": "http://d.opencalais.com/cat/Calais/Law_Crime",
"classifierName": "Calais",
"categoryName": "Law_Crime",
"score": 0.869
}
I am trying to deserialise the above exact string into an object:
public class OpenCalaisResult
{
public string _typeGroup {get; set; }
public string category { get; set; }
public string categoryName { get; set; }
public string classifierName { get; set; }
public decimal score { get; set; }
}
I am trying this code:
OpenCalaisResult myObject = (OpenCalaisResult)JsonConvert.DeserializeObject(myString, typeof(OpenCalaisResult), settings);
I get an exception:
{"Error converting value
\"http://d.opencalais.com/dochash-1/0701d73f-2f99-39e1-8c29-e61ee8bf3238/cat/1\"
to type 'MyApp.Parsers.JsonTypes.OpenCalaisResult'. Path
'', line 1, position 78."}
Any idea what I am doing wrong?

your json should be like this
{
"http://d.opencalais.com/dochash-1/0701d73f-2f99-39e1-8c29-e61ee8bf3238/cat/1":
{
"_typeGroup": "topics",
"category": "http://d.opencalais.com/cat/Calais/Law_Crime",
"classifierName": "Calais",
"categoryName": "Law_Crime",
"score": 0.869
}
}

http://www.json.org/
Shows objects have the form ...
{ ... }
The form of your JSON is ...
x : { ... }
I'm guessing that 'x' is the type of the class being [de]serialised ... I don't believe it's supported by your library.
JSON support is a bit random.

Related

Cannot deserealize Json string (C#)

I have JSON string that came from AWS Lambda:
"body": "{'From': nemesises#live.com, 'To': suhomlin.eugene93#gmail.com}",
And try to deserialize it like this
var email = JsonConvert.DeserializeObject<SendEmailMessage>(emailRequest.Message);
Here is the class to what I need to deserialize
public class SendEmailMessage
{
public string From { get; set; }
public string To { get; set; }
public object Data { get; set; }
public int TemplateId { get; set; }
public List<string> Attachments { get; set; }
}
But I get this error
Newtonsoft.Json.JsonReaderException: Unexpected content while parsing JSON. Path 'From', line 1, position 11.
How I can solve this?
You need to wrap the entire json in {}.
{
"body": "{'From': nemesises#live.com, 'To': suhomlin.eugene93#gmail.com}"
}
You can use a site like https://jsonlint.com/ to work out things like this.
So the problem was in the format of the body
Here the correct format is
{
"Records": [
{
"messageId": "19dd0b57-b21e-4ac1-bd88-01bbb068cb78",
"receiptHandle": "MessageReceiptHandle",
"body": "{ \"Message\":\"{ 'from': 'nemesises#live.com','to': 'suhomlin.eugene93#gmail.com',}\"}",
"attributes": {
"ApproximateReceiveCount": "1",
"SentTimestamp": "1523232000000",
"SenderId": "123456789012",
"ApproximateFirstReceiveTimestamp": "1523232000001"
},
"messageAttributes": {},
"md5OfBody": "7b270e59b47ff90a553787216d55d91d",
"eventSource": "aws:sqs",
"eventSourceARN": "arn:{partition}:sqs:{region}:123456789012:MyQueue",
"awsRegion": "{region}"
}
]
}

Read Json string with Newtonsoft C#

I cannot read json string with c#. I getting error while reading.
Json file
{
"Invoice": {
"Description": "New",
"InvoiceTypeId": "3d166468-3923-11e6-9e7c-40e230cfb8ae",
"CustomerAccountsId": "TEST",
"InvoiceDate": "2016-06-27",
"PayableDate": "2016-06-27",
"Prefix": "A",
"Serial": "34222",
"tag": "TEST"
},
"InvoiceLine": [
{
"ValueId": "c41d3d85-3a1e-11e6-9e7c-40e230cfb8ae",
"Qantity": "3",
"UnitId": "a72e0dde-3953-11e6-9e7c-40e230cfb8ae",
"Price": "1.500,00",
"VatRateId": "18",
"LineVat": "810,00",
"LineTotal": "5.310,00",
"Vat": "00a239f1-3c3a-11e6-9e7c-40e230cfb8ae"
},
{
"ValueId": "fd11b236-3952-11e6-9e7c-40e230cfb8ae",
"Qantity": "5",
"UnitId": "a72e0dde-3953-11e6-9e7c-40e230cfb8ae",
"Price": "1.000,00",
"VatRateId": "18",
"LineVat": "900,00",
"LineTotal": "5.900,00",
"Vat": "00a239f1-3c3a-11e6-9e7c-40e230cfb8ae"
}
]
}
"Error reading JArray from JsonReader. Current JsonReader item is not an array: StartObject. Path '', line 1, position 1."
JArray jsonVal = JArray.Parse(jsonArr) as JArray;
dynamic vars = jsonVal;
But everything right, I do not see bugs.
Don't do this...you're parsing to an array when it's clearly a complex object.
Use a converter such as Visual Studio or json2csharp.com to create the appropriate target object structure:
public class Invoice
{
public string Description { get; set; }
public string InvoiceTypeId { get; set; }
public string CustomerAccountsId { get; set; }
public string InvoiceDate { get; set; }
public string PayableDate { get; set; }
public string Prefix { get; set; }
public string Serial { get; set; }
public string tag { get; set; }
}
public class InvoiceLine
{
public string ValueId { get; set; }
public string Qantity { get; set; }
public string UnitId { get; set; }
public string Price { get; set; }
public string VatRateId { get; set; }
public string LineVat { get; set; }
public string LineTotal { get; set; }
public string Vat { get; set; }
}
public class Invoices
{
public Invoice Invoice { get; set; }
public List<InvoiceLine> InvoiceLine { get; set; }
}
Then simply use the JsonConvert methods to deserialize.
var parsedJson = JsonConvert.DeserializeObject<Invoices>(json);
You can also deserialize it to a dynamic object. Of course this is not ideal but if you don't want to create a whole new type for it, this would work
var vars =JsonConvert.DeserializeObject<dynamic>( jsonArr);
//vars.InvoiceLine
I noticed in the question and a comment you made, "How do I read this?" that you might also be confused on reading JSON which made the error message confusing to you.
You are trying to parse the object as a JArray while your JSON isn't for an array.
If you look at your error message,
"Error reading JArray from JsonReader. Current JsonReader item is not an array: StartObject. Path '', line 1, position 1."
It's immediately throwing an error at the first character on the first line of your JSON and telling you it's not an array.
{ is the first character of your JSON, it was an array than it should start with [ just like if you were writing JavaScript.
Array:
var javaScriptArray = ["This", "Is", "An", "Array"];
Object:
var javaScriptObject = { id: 0, thisIsAnArray: false };
And put it together:
var javaScriptArrayOfObjects = [ { id: 0, thisIsAnArray: false},{ id: 1, thisIsAnArray: false} ];
You can see that when you look at your JSON (Java Script Object Notation) you should be able to tell if it's an array of objects or an object with arrays.
this should point you to it being a complex object and not an array and David L's answer covers that perfectly.
I just wanted to touch on better understanding the error message.

Deserializing JSON with Child and Inner Childs

I am familiar with JSON.net a bit and can Deserialize the JSON with basic structure (upto one child). I am currently in process of Deserializing the JSON that is returned from Netatmo API. The structure of JSON is complicated for me. Following is the basic structure of the JSON,
_id
place
location
Dynamic Value 1
Dynamic Value2
altitude
timezone
mark
measures
Dynamic Value 1
res
Dynamic Value 1
Dynamic Value 1
Dynamic Value 2
type
Dynamic Value 1
Dynamic Value 2
modules
Dynamic Value 1
Dynamic Value 1 and Dynamic Value 2 represents the values that is changed for each id. The complete JSON is given below,
{
"body": [{
"_id": "70:ee:50:02:b4:8c",
"place": {
"location": [-35.174779762001, -5.8918476117544],
"altitude": 52,
"timezone": "America\/Fortaleza"
},
"mark": 0,
"measures": {
"02:00:00:02:ba:2c": {
"res": {
"1464014579": [16.7, 77]
},
"type": ["temperature", "humidity"]
},
"70:ee:50:02:b4:8c": {
"res": {
"1464014622": [1018.1]
},
"type": ["pressure"]
}
},
"modules": ["02:00:00:02:ba:2c"]
}, {
"_id": "70:ee:50:12:40:cc",
"place": {
"location": [-16.074257294385, 11.135715243973],
"altitude": 14,
"timezone": "Africa\/Bissau"
},
"mark": 14,
"measures": {
"02:00:00:06:7b:c8": {
"res": {
"1464015073": [26.6, 78]
},
"type": ["temperature", "humidity"]
},
"70:ee:50:12:40:cc": {
"res": {
"1464015117": [997]
},
"type": ["pressure"]
}
},
"modules": ["02:00:00:06:7b:c8"]
}],
"status": "ok",
"time_exec": 0.010364055633545,
"time_server": 1464015560
}
I am confused by looking at the complex structure of this JSON. For single level of JSON I have used this code in the past,
IList<lstJsonAttributes> lstSearchResults = new List<lstJsonAttributes>();
foreach (JToken objResult in objResults) {
lstJsonAttributes objSearchResult = JsonConvert.DeserializeObject<lstJsonAttributes>(objResult.ToString());
lstSearchResults.Add(objSearchResult);
}
But for so many child I have yet to understand how the object class will be created. Any guidance will highly appreciated.
Update:
This is what I have achieved so far.
I have created a main class as below,
public class PublicDataClass
{
public string _id { get; set; }
public PublicData_Place place { get; set; }
public string mark { get; set; }
public List<string> modules { get; set; }
}
and "Place" class is as follow,
public class PublicData_Place
{
public List<string> location { get; set; }
public string altitude { get; set; }
public string timezone { get; set; }
}
Then I have Deserialized the object in the following code line,
var obj = JsonConvert.DeserializeObject<List<PublicDataClass>>(jsonString);
I can now successfully get all the data except the "measures" which is little bit more complicated.
Using json.net, JSON objects that have arbitrary property names but fixed schemas for their values can be deserialized as a Dictionary<string, T> for an appropriate type T. See Deserialize a Dictionary for details. Thus your "measures" and "res" objects can be modeled as dictionaries.
You also need a root object to encapsulate your List<PublicDataClass>, since your root JSON container is an object like so: { "body": [{ ... }] }.
Thus you can define your classes as follows:
public class RootObject
{
public List<PublicDataClass> body { get; set; }
public string status { get; set; }
public double time_exec { get; set; }
public int time_server { get; set; }
}
public class PublicDataClass
{
public string _id { get; set; }
public PublicData_Place place { get; set; }
public int mark { get; set; }
public List<string> modules { get; set; }
public Dictionary<string, Measure> measures { get; set; }
}
public class PublicData_Place
{
public List<double> location { get; set; } // Changed from string to double
public double altitude { get; set; } // Changed from string to double
public string timezone { get; set; }
}
public class Measure
{
public Measure()
{
this.Results = new Dictionary<string, List<double>>();
this.Types = new List<string>();
}
[JsonProperty("res")]
public Dictionary<string, List<double>> Results { get; set; }
[JsonProperty("type")]
public List<string> Types { get; set; }
}
Then do
var root = JsonConvert.DeserializeObject<RootObject>(jsonString);
var obj = root.body;
I've worked with XML for a few years and my change to JSON structure I've got a little confused too, always that I want to see how an object look like I use this web site jsoneditoronline Just copy and paste your JSON and click on arrow to parse to an object, I hope it helps until you get used to JSON structure.

Saving JSON data into a C# custom object

I've been playing with this for the past few days and I'm hoping someone could shed some light on what the issue could be.
I have this custom object that I created:
public class WorldInformation
{
public string ID { get; set; }
public string name { get; set; }
}
and this JSON data:
string world = "[{\"id\":\"1016\",\"name\":\"Sea of Sorrows\"}, {\"id\":\"1008\",\"name\":\"Jade Quarry\"},{\"id\":\"1017\",\"name\":\"Tarnished Coast\"},{\"id\":\"1006\",\"name\":\"Sorrow's Furnace\"},{\"id\":\"2014\",\"name\":\"Gunnar's Hold\"}]";
and I can sucessfully save the data in my custom object by deserializing it:
List<WorldInformation> worlds = JsonConvert.DeserializeObject<List<WorldInformation>>(world);
But...
When I create a custom object like this
public class EventItems
{
public string World_ID { get; set; }
public string Map_ID { get; set; }
public string Event_ID { get; set; }
public string State { get; set; }
}
and have JSON data like this:
string eventItem = "{\"events\":[{\"world_id\":1011,\"map_id\":50,\"event_id\":\"BAD81BA0-60CF-4F3B-A341-57C426085D48\",\"state\":\"Active\"},{\"world_id\":1011,\"map_id\":50,\"event_id\":\"330BE72A-5254-4036-ACB6-7AEED05A521C\",\"state\":\"Active\"},{\"world_id\":1011,\"map_id\":21,\"event_id\":\"0AC71429-406B-4B16-9F2F-9342097A50AD\",\"state\":\"Preparation\"},{\"world_id\":1011,\"map_id\":21,\"event_id\":\"C20D9004-DF6A-4217-BF25-7D6B5788A94C\",\"state\":\"Success\"}]}";
I get an error when I try to deserialize it
List<EventItems> events = JsonConvert.DeserializeObject<List<EventItems>>(eventItem);
The error message I get is:
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[WebApplication1.EventItems]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'events', line 1, position 10.
Unforturnately there isn't a way to specify the root Json element like the XmlSerializer.
See How to deserialize JSON array with "root" element for each object in array using Json.NET?
public class EventItems
{
public EventItems()
{
Events = new List<EventItem>();
}
public List<EventItem> Events { get; set; }
}
public class EventItem
{
public string World_ID { get; set; }
public string Map_ID { get; set; }
public string Event_ID { get; set; }
public string State { get; set; }
}
Usage:
string eventItem = "{\"events\":[{\"world_id\":1011,\"map_id\":50,\"event_id\":\"BAD81BA0-60CF-4F3B-A341-57C426085D48\",\"state\":\"Active\"},{\"world_id\":1011,\"map_id\":50,\"event_id\":\"330BE72A-5254-4036-ACB6-7AEED05A521C\",\"state\":\"Active\"},{\"world_id\":1011,\"map_id\":21,\"event_id\":\"0AC71429-406B-4B16-9F2F-9342097A50AD\",\"state\":\"Preparation\"},{\"world_id\":1011,\"map_id\":21,\"event_id\":\"C20D9004-DF6A-4217-BF25-7D6B5788A94C\",\"state\":\"Success\"}]}";
var items = JsonConvert.DeserializeObject<EventItems>(eventItem);
In first case your json is array of objects, so deserialization into a list of your class type succeeds.
In second case, your json is an object, and its "events" property is set to an array of objects, so it cannot be deserialized into a list.
What you may do, is change your class declaration:
public class EventItem
{
public string World_ID { get; set; }
public string Map_ID { get; set; }
public string Event_ID { get; set; }
public string State { get; set; }
}
public class EventItems
{
public EventItem[] Events { get; set; }
}
And deserialize it:
EventItems events = JsonConvert.DeserializeObject<EventItems>(eventItem);
Simply remove the object events from the 2nd JSON string:
string eventItem = "[{\"world_id\":1011,\"map_id\":50,\"event_id\":\"BAD81BA0-60CF-4F3B-A341-57C426085D48\",\"state\":\"Active\"},{\"world_id\":1011,\"map_id\":50,\"event_id\":\"330BE72A-5254-4036-ACB6-7AEED05A521C\",\"state\":\"Active\"},{\"world_id\":1011,\"map_id\":21,\"event_id\":\"0AC71429-406B-4B16-9F2F-9342097A50AD\",\"state\":\"Preparation\"},{\"world_id\":1011,\"map_id\":21,\"event_id\":\"C20D9004-DF6A-4217-BF25-7D6B5788A94C\",\"state\":\"Success\"}]";
It seems that your JSON string is not the same in both examples.
On the first example, you're using a simple JSON array:
[
{
"id": "1016",
"name": "Sea of Sorrows"
},
{
"id": "1008",
"name": "Jade Quarry"
},
{
"id": "1017",
"name": "Tarnished Coast"
},
{
"id": "1006",
"name": "Sorrow's Furnace"
},
{
"id": "2014",
"name": "Gunnar's Hold"
}
]
And on the second example, you're assigning your array to an object (events):
{
"events":
[
{
"world_id": 1011,
"map_id": 50,
"event_id": "BAD81BA0-60CF-4F3B-A341-57C426085D48",
"state": "Active"
},
{
"world_id": 1011,
"map_id": 50,
"event_id": "330BE72A-5254-4036-ACB6-7AEED05A521C",
"state": "Active"
},
{
"world_id": 1011,
"map_id": 21,
"event_id": "0AC71429-406B-4B16-9F2F-9342097A50AD",
"state": "Preparation"
},
{
"world_id": 1011,
"map_id": 21,
"event_id": "C20D9004-DF6A-4217-BF25-7D6B5788A94C",
"state": "Success"
}
]
}

Parsing multi-level JSON array

I'm trying to get objects from a multi-level JSON array. This is the an example table:
array(2) {
["asd"]=>
array(3) {
["id"]=>
int(777)
["profile"]=>
array(4) {
["username"]=>
string(5) "grega"
["email"]=>
string(18) "random#example.com"
["image"]=>
string(16) "http...image.jpg"
["age"]=>
int(26)
}
["name"]=>
string(5) "Grega"
}
["be"]=>
array(4) {
["username"]=>
string(5) "grega"
["email"]=>
string(18) "random#example.com"
["image"]=>
string(16) "http...image.jpg"
["age"]=>
int(26)
}
}
The string I'm trying to reach is either of the emails (example). This is how I try it:
public class getAsd
{
public string asd;
}
public class Profile
{
public string username { get; set; }
public string email { get; set; }
public string image { get; set; }
public string age { get; set; }
}
}
And then using JavaScriptSerilization.Deserilize<Asd>(jsonData); to deserilize it, but when I try the same with "Profile", it gives me the following error:
No parameterless constructor defined for type of 'System.String'.
JSON:
{"asd":{"id":777,"profile":{"username":"grega","email":"random#example.com","image":"http...image.jpg","age":26},"name":"Grega"},"be":{"username":"grega","email":"random#example.com","image":"http...image.jpg","age":26}}
And idea what might be wrong?
[EDIT: Smarm removed. OP did add JSON in an edit.]
Your profile class, as JSON, should resemble the following.
{
"username":"grega",
"email":"random#example.com",
"image":"http...image.jpg",
"age":"26",
"roles": [
{"name": "foo"},
{"name": "bar"}
]
}
array should not show up in JSON unless its part of a property name ("codearray") or property value("There's no 'array' in JSON. There's no 'array' in JSON.").
Arrays of objects in JSON are encased in square brackets [] and comma-delimited. An array/collection of profiles in JSON:
[
{
"username":"gretta",
"email":"mrshansel#example.com",
"image":"http...image.jpg",
"age":"37",
"roles": [
{"name": "foo"},
{"name": "bar"}
]
},
{
"username":"methusaleh",
"email":"old#men.org",
"image":"http...image.jpg",
"age":"2600",
"roles": [
{"name": "foo"},
{"name": "},
{"name": "bar"}
]
},
{
"username":"goldilocks",
"email":"porridge#bearshous.com",
"image":"http...image.jpg",
"age":"11",
"roles": [
{"name": "foo"}
]
}
]
While that may not fully answer your question, could you start with that and update your question?
EDIT:
See this answer by Hexxagonal for the complete approach.
Alright, here was what a "basic" version of your classes would be. You should really follow a standard of having properties have their first letter capitalized. Since you did not do this earlier, I maintained that style.
public class Type1
{
public TypeAsd asd { get; set; }
public TypeBe be { get; set; }
}
public class TypeAsd
{
public int id { get; set; }
public TypeBe profile { get; set; }
public string name { get; set; }
}
public class TypeBe
{
public string username { get; set; }
public string email { get; set; }
public string image { get; set; }
public int age { get; set; }
}
You deserialization code would then look something like the following:
string jsonString = "{\"asd\":{\"id\":777,\"profile\":{\"username\":\"grega\",\"email\":\"random#example.com\",\"image\":\"http...image.jpg\",\"age\":26},\"name\":\"Grega\"},\"be\":{\"username\":\"grega\",\"email\":\"random#example.com\",\"image\":\"http...image.jpg\",\"age\":26}}";
JavaScriptSerializer serializer = new JavaScriptSerializer();
Type1 obj = serializer.Deserialize<Type1>(jsonString);

Categories