Newtonsoft JSON Deserialization not working as expected [closed] - c#

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 13 hours ago.
Improve this question
Given this JSON
{
"docType": "payment-remittance-v1.4",
"fields": {
"Customer Name": {
"type": "string",
"valueString": "xxx",
"spans": [
{
"offset": 284,
"length": 43
}
]
},
"Payment Reference": {
"type": "string",
"valueString": "3875014846",
"content": "3875014846",
"confidence": 0.92,
"spans": [
{
"offset": 167,
"length": 10
}
]
},
"Remittance Date": {
"type": "date",
"content": "16.02.2023",
"confidence": 0.97,
"spans": [
{
"offset": 180,
"length": 10
}
]
},
},
"confidence": 0.125,
"spans": [
{
"offset": 0,
"length": 1048
}
]
}
And these classes
public class PredictionFields
{
[JsonProperty("Customer Name", Required = Required.Always)]
public BaseField CustomerName { get; set; }
[JsonProperty("Payment Reference", Required = Required.Always)]
public BaseField PaymentReference { get; set; }
}
public class BaseField
{
[JsonProperty("confidence")]
public double Confidence { get; set; }
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("valueNumber")]
public double ValueNumber { get; set; }
[JsonProperty("valueString")]
public string ValueString { get; set; }
[JsonProperty("content")]
public string Content { get; set; }
}
public class Document
{
[JsonProperty("docType")]
public string DocType { get; set; }
[JsonProperty("fields")]
public PredictionFields Fields { get; set; }
[JsonProperty("confidence")]
public double Confidence { get; set; }
}
I get an error Unhandled exception. Newtonsoft.Json.JsonSerializationException: Required property 'Customer Name' not found in JSON. Path 'fields', line 82, position 3.
I'm perplexed as to this because the property is defintely listed in the JSON.
I have created a .NET Fiddle - be glad of any help, have been puzzling this for hours!

Adding the Property Name to PredictionFields should solve the problem:
public class PredictionFields
{
[JsonProperty("Customer Name", Required = Required.Always, PropertyName = "Customer Name")]
public BaseField CustomerName { get; set; }
[JsonProperty("Payment Reference", Required = Required.Always, PropertyName = "Payment Reference")]
public BaseField PaymentReference { get; set; }
}

Related

c# nested json to object (current with json.net)

i am new to c# and json.net.
I have a json configuration file and try to parse it to objects. But how can i map the relations correctly in the objects?
Currently the property in project loop is null.
And can the objects map "automatically" without mapping each property name/value?
I can also change the json!
configuration.json:
{
"debug": true,
"log": "database",
"projects": [
{
"name": "Name 1",
"showInfo": false,
"ranges": [
[
5,
6
],
[
9,
10
],
[
15,
20
]
],
"additional": [
{
"name": "subName 1",
"parameter": "ID"
},
{
"name": "subName 2",
"parameter": "ID2"
}
]
},
{
"name": "Name 2",
"showInfo": false,
"ranges": [
[
99,
100
]
]
},
{
"name": "Name 3",
"showInfo": false,
"ranges": [
[
44,
45
]
]
},
{
"name": "Name 4",
"showInfo": false,
"ranges": [
[
12,
14
]
],
"additional": [
{
"name": "subName xy",
"parameter": "ID"
}
]
}
]
}
my try to parse:
Configuration configuration = new Configuration();
JObject jObject = JObject.Parse(File.ReadAllText(filePath));
if (jObject.ContainsKey("debug"))
{
configuration.Debug = (bool) jObject["debug"];
}
if (jObject.ContainsKey("log"))
{
configuration.Log = (string) jObject["log"];
}
//loop projects
JToken projects = jObject["projects"];
foreach (JToken child in projects.Children())
{
var property = child as JProperty;
if (property != null)
{
var test = property.Name;
var test2 = property.Value;
}
}
the objects:
public class Configuration
{
public bool Debug { get; set; } = false;
public string Log { get; set; }
// this is propably wrong
public Dictionary<string, Dictionary<string, Project>> Projects { get; set; }
}
public class Project
{
public string name { get; set; }
public bool showInfo{ get; set; }
// wrong?
public int[,] ranges { get; set; }
// wrong?
public Additional[] Additional{ get; set; }
}
public class Additional
{
public string Name{ get; set; }
public string Parameter { get; set; }
}
You don't need a JObject at all json files can be desterilized to objects it's much more efficient because you don't create unneeded objects.
You Config class is just wrong
public class Configuration
{
public bool Debug { get; set; }
public string Log { get; set; }
public Project[] Projects { get; set; }
}
public class Project
{
public string Name { get; set; }
public bool ShowInfo { get; set; }
public int[][] Ranges { get; set; }
public Additional[] Additional { get; set; }
}
public class Additional
{
public string Name { get; set; }
public string Parameter { get; set; }
}`
Should look like this.
And then use. JsonConvert.DeserializeObject<Configuration>(json); To get the object.
If you have Visual studio it has this cool feature called paste special where you can just past your json and it will create a proper class for deserialization. It's under Edit-> Paste special-> Paste json as class

how to create json feed [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
any one explain me how to develop following type of json.
Json feed contains parent and child nodes with database comtent.
{
"contacts": [
{
"id": "c200",
"name": "Ravi Tamada",
"email": "ravi#gmail.com",
"address": "xx-xx-xxxx,x - street, x - country",
"gender" : "male",
"phone": {
"mobile": "+91 0000000000",
"home": "00 000000",
"office": "00 000000"
}
},
{
"id": "c201",
"name": "Johnny Depp",
"email": "johnny_depp#gmail.com",
"address": "xx-xx-xxxx,x - street, x - country",
"gender" : "male",
"phone": {
"mobile": "+91 0000000000",
"home": "00 000000",
"office": "00 000000"
}
},
]
}
Go to this site and paste your json. It will create the following classes for you
public class Phone
{
public string mobile { get; set; }
public string home { get; set; }
public string office { get; set; }
}
public class Contact
{
public string id { get; set; }
public string name { get; set; }
public string email { get; set; }
public string address { get; set; }
public string gender { get; set; }
public Phone phone { get; set; }
}
public class RootObject
{
public List<Contact> contacts { get; set; }
}
Create the RootObject, fill the properties and then serialize it.
That is all.
var root = new RootObject();
//fill the properties
string json = JsonConvert.SerializeObject(root);

Deserializing JSON that has an int as a key in C#

I am trying to deserialize this JSON
{
"39": {
"category": "Miscellaneous",
"country_whitelist": [],
"name": "domain.com",
"url_blacklist": [],
"country_blacklist": [],
"url_whitelist": [
"domain.com"
],
"deals": {
"425215": {
"status": "Ok",
"type": "",
"code": "CODE",
"end_date": "2014-03-01 04:00:00",
"title": "RandomTitle",
"url": "http://domain.com/foo",
"text": "Text Text Text",
"long_title": "Longer Text"
},
"425216": {
"status": "Ok",
"type": "",
"code": "CODE2",
"end_date": "2014-03-01 04:00:00",
"title": "RandomTitle2",
"url": "http://domain.com/bar",
"text": "Text Text Text",
"long_title": "Longer Text"
}
},
"88x31": "http://someimage/88x31.png",
"subcategory": "Other"
},
"40": {
"category": "Miscellaneous",
"country_whitelist": [],
"name": "domain.com",
"url_blacklist": [],
"country_blacklist": [],
"url_whitelist": [
"domain.com"
],
"products": {
"425215": {
"status": "Ok",
"type": "",
"code": "CODE",
"end_date": "2014-03-01 04:00:00",
"title": "RandomTitle",
"url": "http://domain.com/foo",
"text": "Text Text Text",
"long_title": "Longer Text"
},
"425216": {
"status": "Ok",
"type": "",
"code": "CODE2",
"end_date": "2014-03-01 04:00:00",
"title": "RandomTitle2",
"url": "http://domain.com/bar",
"text": "Text Text Text",
"long_title": "Longer Text"
}
},
"88x31": "http://someimage/88x31.png",
"subcategory": "Other"
}
}
I tried using Json.NET and I tried using ServiceStack's deserializer but I can't seem to get any type of representation for this JSON.
The main thing that is blocking me I believe is that the keys are Int but I don't have control on the JSON I receive.
This is the C# classes I have built
public class product
{
public string status { get; set; }
public string type { get; set; }
public string code { get; set; }
public string end_date { get; set; }
public string title { get; set; }
public string url { get; set; }
public string text { get; set; }
public string long_title { get; set; }
}
public class Merchant
{
public string category { get; set; }
public List<string> country_whitelist { get; set; }
public string name { get; set; }
public List<string> url_blacklist { get; set; }
public List<string> country_blacklist { get; set; }
public List<string> url_whitelist { get; set; }
public List<product> products { get; set; }
public string subcategory { get; set; }
}
public class Data
{
public Dictionary<int, Merchant> MainMerchants { get; set; }
}
I prefer using ServiceStack but any other deserializer that works will be great
var data = client.Get(json);
Getting your data types mapped correctly:
It is possible to deserialize your JSON. As you correctly identified you can deserialize to a Dictionary<int, Merchant>.
But you will need to change your definition of products in the Merchant class to be a Dictionary<int, Product>. It needs to be a dictionary here to handle your numeric key. List<Product> won't work.
Also to handle the 88x31 property you can use a DataMember(Name = '88x31') mapping to map it to something c# likes, like image88x31. Unfortunately this does mean your DTO properties become opt-in so you will then need to decorate all members. Add using System.Runtime.Serialization;
Once you make those changes such that:
// Note I capitalized Product
public class Product
{
public string status { get; set; }
public string type { get; set; }
public string code { get; set; }
public string end_date { get; set; }
public string title { get; set; }
public string url { get; set; }
public string text { get; set; }
public string long_title { get; set; }
}
/*
* Use DataMember to map the keys starting with numbers to an alternative c# compatible name.
* Unfortunately this requires properties to opt in to the data contract.
*/
[DataContract]
public class Merchant
{
[DataMember]
public string category { get; set; }
[DataMember]
public List<string> country_whitelist { get; set; }
[DataMember]
public string name { get; set; }
[DataMember]
public List<string> url_blacklist { get; set; }
[DataMember]
public List<string> country_blacklist { get; set; }
[DataMember]
public List<string> url_whitelist { get; set; }
[DataMember]
public Dictionary<int, Product> products { get; set; }
[DataMember]
public string sub_category { get; set; }
// This maps the 88x31 key to a c# appropriate name
[DataMember(Name = "88x31")]
public string image88x31 { get; set; }
}
Then you will be able to deserialize into Dictionary<int, Merchant> without any issues.
JsonSerializer.DeserializeFromString<Dictionary<int, Merchant>>("YOUR JSON STRING");
Using in a ServiceStack Service:
If you want to be able to send this request directly to a ServiceStack service, then you can use a RequestBinder to deserialize into this complex type. Given this service:
Request DTO:
[Route("/Merchants", "POST")]
public class MerchantsRequest
{
public Dictionary<int, Merchant> MainMerchants { get; set; }
}
Simple Action Method:
public class MerchantsService : Service
{
public void Post(MerchantsRequest request)
{
var merchant39 = request.MainMerchants.First(p=>p.Key == 39).Value;
Console.WriteLine("Name: {0}\nImage: {1}\nProduct Count: {2}", merchant39.name, merchant39.image88x31, merchant39.products.Count);
var merchant40 = request.MainMerchants.First(p=>p.Key == 40).Value;
Console.WriteLine("Name: {0}\nImage: {1}\nProduct Count: {2}", merchant40.name, merchant40.image88x31, merchant40.products.Count);
}
}
AppHost Configuration:
In your AppHost Configure method you would need to add a binder to the request type. i.e. typeof(MerchantsRequest) like so:
public override void Configure(Funq.Container container)
{
Func<IRequest, object> merchantsRequestBinder = delegate(IRequest request) {
var json = WebUtility.HtmlDecode( request.GetRawBody() );
return new MerchantsRequest { MainMerchants = JsonSerializer.DeserializeFromString<Dictionary<int, Merchant>>(json) };
};
RequestBinders.Add(typeof(MerchantsRequest), merchantsRequestBinder);
...
}
This binder method will convert the json you are sending into a MerchantsRequest. Then you can use it like a regular ServiceStack request.
Full Source Code Here
A fully working example of console application, demonstrating the conversion of the complex JSON to a service request.
Note: I notice in your JSON that you have property deals on one object, and products on another, I assumed this was a typo, as you don't have a corresponding property on in the class for deals.
In your json string, for the products node, should it be this? as the type where it converted from is a List instead of dictionary?
I can get it work change it to following json string
"products": [{
"status": "Ok",
"type": "",
"code": "CODE",
"end_date": "2014-03-01 04:00:00",
"title": "RandomTitle",
"url": "http://domain.com/foo",
"text": "Text Text Text",
"long_title": "Longer Text"
},
{
"status": "Ok",
"type": "",
"code": "CODE2",
"end_date": "2014-03-01 04:00:00",
"title": "RandomTitle2",
"url": "http://domain.com/bar",
"text": "Text Text Text",
"long_title": "Longer Text"
}],

Update complex entity in db

I am working with facebook RTU and get json updates on the payments of my application`s users.
To have a better customer service i want to save all the json string facebook sends me , but in an ordered way.
For example,
I am getting this json:
{
"id": "3603105474213890",
"user": {
"name": "Daniel Schultz",
"id": "221159"
},
"application": {
"name": "Friend Smash",
"namespace": "friendsmashsample",
"id": "241431489326925"
},
"actions": [
{
"type": "charge",
"status": "completed",
"currency": "USD",
"amount": "0.99",
"time_created": "2013-03-22T21:18:54+0000",
"time_updated": "2013-03-22T21:18:55+0000"
}
],
"refundable_amount": {
"currency": "USD",
"amount": "0.99"
},
"items": [
{
"type": "IN_APP_PURCHASE",
"product": "http://www.friendsmash.com/og/friend_smash_bomb.html",
"quantity": 1
}
],
"country": "US",
"created_time": "2013-03-22T21:18:54+0000",
"payout_foreign_exchange_rate": 1,
"disputes": [
{
"user_comment": "I didn't receive my item! I want a refund, please!",
"time_created": "2013-03-24T18:21:02+0000",
"user_email": "email\u0040domain.com"
}
]
}
And i want to save it in db but not as a string, as an object this style and also have the option to query by field value from my db.
public class PaymentDetailsDto
{
public string id { get; set; }
public PaidUserDto user { get; set; }
public PaidApplicationDto application { get; set; }
public List<PaymentActionDto> actions { get; set; }
public RefundableAmountDto refundable_amount { get; set; }
public List<PaymentItemDto> items { get; set; }
public string country { get; set; }
public string created_time { get; set; }
public int test { get; set; }
public int payout_foreign_exchange_rate { get; set; }
public List<DisputeDto> disputes { get; set; }
}
How do you suggest representing this Entity in db?
As you see i have three List objects in my Root object and this it what make it a little but complicated to decide how to save it.
We are not gonna use EntityFramework or NHibernate.

How to convert JSON to C# classes?

I have a complex JSON object that I want represent as C# class. I have a head start on the parent class called "Form", but how can I represent a collection for different types (see the "elements" object below)?
Here is the JSON object:
{
"action": "index.html",
"method": "post",
"elements":
[
{
"type": "fieldset",
"caption": "User information",
"elements":
[
{
"name": "email",
"caption": "Email address",
"type": "text",
"placeholder": "E.g. user#example.com",
"validate":
{
"email": true
}
},
{
"name": "password",
"caption": "Password",
"type": "password",
"id": "registration-password",
"validate":
{
"required": true,
"minlength": 5,
"messages":
{
"required": "Please enter a password",
"minlength": "At least {0} characters long"
}
}
},
{
"name": "password-repeat",
"caption": "Repeat password",
"type": "password",
"validate":
{
"equalTo": "#registration-password",
"messages":
{
"equalTo": "Please repeat your password"
}
}
},
{
"type": "radiobuttons",
"caption": "Sex",
"name": "sex",
"class": "labellist",
"options":
{
"f": "Female",
"m": "Male"
}
}
]
]
}
The class I have start looks like this:
public class Form
{
public Guid id
{
get;
set;
}
public string action
{
get;
set;
}
public string method
{
get;
set;
}
public ??? elements
{
get;
set;
}
public Form()
{
}
}
How do I handle the "elements" property to get the desired JSON output?
I am using WCF 4.0 with these atributes in the web.config: automaticFormatSelectionEnabled="false", defaultOutgoingResponseFormat="Json". Any help or ideas would be greatly appreciated.
If you don't have the liberty of using dynamic types from .NET 4 or would like to leverage the benefits that static typing provide, the JSON Class Generator project on codeplex will generate c# classes given a json input string. (shameless plug) I've also taken code from this project and slapped a web UI on it.
Wow. Fascinating question. Maybe use ExpandoObject / dynamic?
http://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject.aspx
http://blogs.msdn.com/b/csharpfaq/archive/2009/10/01/dynamic-in-c-4-0-introducing-the-expandoobject.aspx?PageIndex=4
Or anonymous types I think are serializable with the built-in .NET JSON serializer.
You do not need to try and create the class structure manually.
Sometimes it is rather frustrating too. :)
There is a visual studio command you can use (I think vs2015 and later):
On a new class file click Menu => Edit => Paste Special
Select "Paste JSON as Classes"
Now specifically in your JSON there is an error, you are missing the closing curly-brace of first "element" object.
Below is the corrected JSON:
{
"action": "index.html",
"method": "post",
"elements": [
{
"type": "fieldset",
"caption": "User information",
"elements": [
{
"name": "email",
"caption": "Email address",
"type": "text",
"placeholder": "E.g. user#example.com",
"validate": {
"email": true
}
},
{
"name": "password",
"caption": "Password",
"type": "password",
"id": "registration-password",
"validate": {
"required": true,
"minlength": 5,
"messages": {
"required": "Please enter a password",
"minlength": "At least {0} characters long"
}
}
},
{
"name": "password-repeat",
"caption": "Repeat password",
"type": "password",
"validate": {
"equalTo": "#registration-password",
"messages": {
"equalTo": "Please repeat your password"
}
}
},
{
"type": "radiobuttons",
"caption": "Sex",
"name": "sex",
"class": "labellist",
"options": {
"f": "Female",
"m": "Male"
}
}
]
}
]
}
And the corresponding Classes:
public class Rootobject
{
public string action { get; set; }
public string method { get; set; }
public Element[] elements { get; set; }
}
public class Element
{
public string type { get; set; }
public string caption { get; set; }
public Element1[] elements { get; set; }
}
public class Element1
{
public string name { get; set; }
public string caption { get; set; }
public string type { get; set; }
public string placeholder { get; set; }
public Validate validate { get; set; }
public string id { get; set; }
public string _class { get; set; }
public Options options { get; set; }
}
public class Validate
{
public bool email { get; set; }
public bool required { get; set; }
public int minlength { get; set; }
public Messages messages { get; set; }
public string equalTo { get; set; }
}
public class Messages
{
public string required { get; set; }
public string minlength { get; set; }
public string equalTo { get; set; }
}
public class Options
{
public string f { get; set; }
public string m { get; set; }
}
If you just want to make sure all this unknown data gets deserialized and can be reserialized at some point in the future, I suggest the usage of IExtensibleDataObject.
Here are some samples to get you started. Hope this helps! (If you already knew this and were looking for something different...let me know!)
Forward-Compatible Data Contracts
Data Contract Versioning
Useful clarifying thread on the topic at MSDN forums

Categories