C# Json.net deserialize nested json as string - c#

I have the following json string
{
"property1" : "value",
"property2" : 2,
"property3" : { "subprperty1" : "value" }
}
and I want to deserialize it (using Newtonsoft's Json.net) but keep property3 as a string.
So I have created the following model class
class JsonModel {
string property1 {get; set;}
int property2 {get; set;}
string property3 {get; set;}
}
But when i deserialize it using JsonConvert.DeserializeObject<JsonModel>(json_string); I get the following error :
Newtonsoft.Json.JsonReaderException: 'Unexpected character encountered while parsing value: {.

"property3" : { "subprperty1" : "value" }
This isn't nested json, its just a standard json object
Update
from your comments, i think you want a generic property. If your use case is you know before hand what is coming back, and there is some subset that is changing, generics might be where you should be
So you could just deserialize it in the standard way
class JsonModel<T>
{
string property1 {get; set;}
int property2 {get; set;}
T property3 {get; set;}
}
class SomeOtherMagicalClass
{
string subprperty1 {get; set;}
}
...
var results = JsonConvert.DeserializeObject<JsonModel<SomeOtherMagicalClass>>(json_string);

Because property3 is an object instead of a string.
You can try to use a class to carry it.
public class Property3
{
public string subprperty1 { get; set; }
}
public class JsonModel
{
public string property1 { get; set; }
public int property2 { get; set; }
public Property3 property3 { get; set; }
}
Note
There are two way can create model easily.
You can use Web Essentials in Visual Studio, use Edit > Paste special > paste JSON as a class, you can easier to know the relation between Json and model.
If you can't use Web Essentials you can instead of use http://json2csharp.com/ online JSON to Model class.
You can try to use those models to carry your JSON Format.

Well, if the task is to deserialize object while preserving property3 as json string we could do two things.
First: Parse the object using JObject.Parse :
class JsonModel {
public string property1 { get; set; }
public int property2 { get; set; }
public string property3 { get; set; }
}
var json_string = "{ \"property1\" : \"value\", \"property2\" : 2, \"property3\" : { \"subprperty1\" : \"value\" } }";
var jObj = JObject.Parse(json_string);
var obj = new JsonModel()
{
property1 = jObj["property1"].ToString(),
property2 = (int) jObj["property2"],
property3 = jObj["property3"].ToString(),
};
Console.WriteLine(obj.property3);
Second: deserialize the obj to dictionary of objects:
var dict = JsonConvert.DeserializeObject<Dictionary<string, object>>(json_string);
Console.WriteLine(dict["property3"].ToString());
Both output the same:
{ "subprperty1": "value" }

Related

Newtonsoft.Json NullValueHandling=Ignore doesn't seem to work

C# with Newtonsoft.Json 13.0.2. I am deserializing a JSON string as such
var car = JsonConvert.DeserializeObject<Car>(resp);
where resp looks like this:
{
"perf": {
"perfRef": null,
"perfTest": {
"value": 1.2,
"unit": "percent"
}
}
}
My class looks like this:
public partial class perf
{
[Newtonsoft.Json.JsonProperty("perfRef", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public PerfRef perfRef { get; set; }
[Newtonsoft.Json.JsonProperty("perfTest", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public PerfTest perfTest { get; set; }
}
But I keep getting an exception
Newtonsoft.Json.JsonSerializationException: Required property 'perfRef' expects a non-null value. Path 'perf'
I don't get why this is happening. I thought the NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore would override any 'Required' option. Am I just misinterpreting how the decorators work?
you have Required which means you cannot have a null value for the perfRef
property.
there are ways to solve this.
either remove Required or provide the value to this property or set the Required attribute to AllowNull or Default.
Note: NullValueHandling Ignore means that null values will be ignored when serializing and deserializing JSON.
Could it be that the cause is that the json-string is wrapped with {"Perf": {...}} and you need an additional class to deserialize it.
My sample array [...] has two json-strings. Both contain the same object {...}
the first wraps it with {"Perf": {...}} like your sample
the second does not.
[
{"Perf": {"perfRef":null, "perfTest":{"value":"1.2","unit":"percent"}}},
{"perfRef":null, "perfTest":{"value":"1.2","unit":"percent"}}
]
You can deserialize the first json string json[0] = {"Perf": {"perfRef":null, "perfTest":{"value":"1.2","unit":"percent"}}} using a class that acts as a wrapper (here JsonResponse):
// to deserialize
// {"Perf": {"perfRef":null, "perfTest":{"value":"1.2","unit":"percent"}}}
public class JsonResponse{
public Perf Perf {get; set;}
}
// use
JsonResponse resp0 = JsonConvert.DeserializeObject<JsonResponse>(json[0]);
If the json-string would not be wrapped then there is no need for a wrapper class
// to deserialize json[1]
// {"perfRef":null, "perfTest":{"value":"1.2","unit":"percent"}}
// use
Perf resp1 = JsonConvert.DeserializeObject<Perf>(json[1]);
This is a lingpad-program that deserializes both json strings:
void Main()
{
// for {"Perf": {...}} a wrapper class is needed
JsonResponse withWrap = JsonConvert.DeserializeObject<JsonResponse>(GetResp()[0]);
// for {...} not
Perf noWrap = JsonConvert.DeserializeObject<Perf>(GetResp()[1]);
withWrap.Dump("Object {...} wrapped in JsonResponse: {Perf: {...}}");
noWrap.Dump("Object {...} not wrapped");
}
// You can define other methods, fields, classes and namespaces here
public string[] GetResp(){
string[] responses = {"""
{"Perf":{"perfRef":null,"perfTest":{"value":"1.2","unit":"percent"}}}
""",
"""
{"perfRef":null,"perfTest":{"value":"1.2","unit":"percent"}}
"""};
return responses;
}
public class JsonResponse{
public Perf Perf {get; set;}
}
public class PerfTest{
public string? Unit {get; set;}
public double? Value {get; set;}
}
public class Perf{
[Newtonsoft.Json.JsonProperty("perfRef")]
public string PerfRef { get; set; }
//public PerfRef perfRef { get; set; }
[Newtonsoft.Json.JsonProperty("perfTest")]
public PerfTest PerfTest { get; set; }
}
The result of the deserialized object JsonResponse and Perf are on the right side.

Deserialize an array inside a json object using JsonConvert.DeserializeObject()

I have a requirement where I have incoming json object of the following format:
{
"CustomerList": {
"Customer": [{
"CustomerCode" : "C123",
"CustomerName" : "Peter"
},
{
"CustomerCode" : "C456",
"CustomerName" : "John"
}]
}
}
And I have the my C# object of the following Format:
[System.Xml.Serialization.XmlArrayItemAttribute(IsNullable = "false")]
public Customer[] CustomerList
{
get; set;
}
[System.Xml.Serialization.XmlTypeAttribute()]
public class Customer
{
public string CustomerCode {get; set;}
public string CustomerName {get; set;}
}
During Deserialization using JsonConvert.DeserializeObject(), I get the following error:
Cannot deserialize the current JSON object into type Customer[], because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
On my side the limitation is that I cannot change the incoming JSON object and neither can I modify the C# object structure. So the ask is that, is there a way to map the Customer node in the incoming Json, to the CustomerList C# array directly, without needing to rename or change the structure of either?
Based on the JSON you have shared, you need to have following class structure.
public class Customer {
public string CustomerCode { get; set; }
public string CustomerName { get; set; }
}
public class CustomerList {
public List<Customer> Customer { get; set; }
}
public class RootObject {
public CustomerList CustomerList { get; set; }
}
and then you need to deserizalize the JSON as following.
RootObject obj = JsonConvert.DeserializeObject<RootObject>(jsonString);
Here jsonString is the string variable which has the JSON string.
I hope you this will help you resolve your issue.
To deserialize the JSON object you need to create a similar C# class.
public class JsonObjectTest {
[JsonPropertyName("CustomerList")]
public Customer CustomerPreList {get;set;}
}
public class Customer {
public List<CustomerObject> Customer {get;set;}
}
public class CustomerObject {
public string CustomerCode { get; set; }
public string CustomerName { get; set; }
}
Afterwards you deserialize the JSON object:
CustomerList xmlData = JsonConvert.DeserializeObject<JsonObjectTest>(jsonObjectString).Select(data =>
new CustomerList = data.CustomerPreList.toArray());
Unfortunately I could not ask you if you have a permission to create new classes (I need more points). If this is the case try AutoMapper to create a mapping policy for this specific case.
Happy coding :)
If you cannot (or do not want to) add new classes, the last two lines of GetCustomers() below should do what you want. Just assign it to the CustomerList property.
public class Customer
{
public string? CustomerCode { get; set; }
public string? CustomerName { get; set; }
}
public Customer[] GetCustomers()
{
string json = #"{
'CustomerList':
{
'Customer': [{
'CustomerCode' : 'C123',
'CustomerName' : 'Peter'
},
{
'CustomerCode' : 'C456',
'CustomerName' : 'John'
}]
}
}";
dynamic? contentObj = JsonConvert.DeserializeObject(json);
return (contentObj?.CustomerList.Customer.ToObject<IList<Customer>>())?.ToArray() ?? new List<Customer>().ToArray();
}
I am working with .NET 6.0 so working with string? but for earlier versions of c# string should do the same. Play with the null handling as required.

How to serialize a JsonArray with C#?

SO I have a Json array as following:
{[data, [{"name":"Micheal Jackson","pic_large":"https://scontent.x.fbcdn.net/v/t1.0-1/p200x200/14909900_10154513795037597_3241587822245799922_n.jpg?oh=54ead7e0ba74b45b632d96da1515ccf8&oe=591C4938","id":"10154729171332597"}
How can I serialize it with C# to parse it into objects and then pass it to the view.
EDIT:
{[data, [{"name":"Sayed Zubair Hashimi","pic_large":"https://scontent.xx.fbcdn.net/v/t1.0-1/p200x200/14909900_10154513795037597_3241587822245799922_n.jpg?oh=54ead7e0ba74b45b632d96da1515ccf8&oe=591C4938","id":"10154729171332597"},{"name":"Junaid Walizada","pic_large":"https://scontent.xx.fbcdn.net/v/t1.0-1/p200x200/14055012_1760562554217155_4937121194048198140_n.jpg?oh=376b49c9d04c2676ebe3d853b122165e&oe=58EA033D","id":"1821833754756701"},{"name":"Mohib Akhondzada","pic_large":"https://scontent.xx.fbcdn.net/v/t1.0-1/s200x200/14264218_592094647641140_6351146344336469735_n.jpg?oh=a8a63893d71f76c45fa3d07389f1700a&oe=59147C84","id":"648198542030750"},{"name":"Za Beah","pic_large":"https://scontent.xx.fbcdn.net/v/t1.0-1/p200x200/15741112_359701871054520_6692094260041596196_n.jpg?oh=6d9a0e73f70145b821c79cbe738090a0&oe=58E5B5B5","id":"360411140983593"},{"name":"Baser Nader","pic_large":"https://scontent.xx.fbcdn.net/v/t1.0-1/p200x200/15094436_10153876544626432_1550234361821853528_n.jpg?oh=e197fa712b3180a20612ecdacb01747c&oe=58E54DEC","id":"10153975726331432"},{"name":"Abasin Deniz","pic_large":"https://scontent.xx.fbcdn.net/v/t1.0-1/p200x200/15698075_440749809647293_7905213567074684088_n.jpg?oh=aeb22664f458d75fc00638ca6fa4ecfc&oe=591F7BB3","id":"444098429312431"}]]}
EDIT2:
Here is how I retrieve above Json.
var appsecret_proof = access_token.GenerateAppSecretProof();
var fb = new FacebookClient(access_token);
dynamic myFeed = await fb.GetTaskAsync(
("me/feed?fields=likes{{name,pic_large}}")
.GraphAPICall(appsecret_proof));
The strings shown in your question are all invalid JSON. A properly formatted JSON might look like this:
{
"data": [{
"name": "Micheal Jackson",
"pic_large": "https://scontent.x.fbcdn.net/v/t1.0-1/p200x200/14909900_10154513795037597_3241587822245799922_n.jpg?oh=54ead7e0ba74b45b632d96da1515ccf8&oe=591C4938",
"id": "10154729171332597"
}]
}
Now if you want to map this to C# class that's pretty easy to do. Just define the models to reflect this structure:
public class Feed
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("pic_large")]
public string PicLarge { get; set; }
}
public class Result
{
[JsonProperty("data")]
public IList<Feed> Feeds { get; set; }
}
and then all that's left is to deserialize the JSON string using a JSON serializer such as Json.NET back to this object structure:
string json = ... the json string shown above
var result = JsonConvert.DeserializeObject<Result>(json);
foreach (var feed in result.Feeds)
{
Console.WriteLine(feed.Name);
}
first you need to create class with properties same as in json and then use the following code :
class obj
{
public string name {get ; set; }
public string pic_large {get ; set; }
public id {get ; set; }
}
using System.Web.Script.Serialization;
.
.
var obj = new JavaScriptSerializer().Deserialize<obj>(jsonString);

Using JSON.net define class with array in Dictionary

I am trying to do the following inside a Dictionary<string,string>
{
"name": "Bob Barker",
"devName": "InformationServices",
"ReturnedData": [{
"level_heading": "blah1",
"DeliverBestMedicalValue": "blah2",
"level_question": "blah3"
}]
}
I can add the name and devName just fine but I am unsure on how to go about adding the ReturnedData part of the array to the list so that it will return as the layout above?
Example code I am using:
febRecords.RootObject febRecordsData = JsonConvert.DeserializeObject<febRecords.RootObject>(serverResponse);
Dictionary<string,string> febFormData = new Dictionary<string,string>();
febFormData.Add("name", data.firstname.ToString());
febFormData.Add("devName", febData["Data"]["DevisionName"].ToString());
febFormData.Add("ReturnedData", ???); //<-this is where I am stuck
return Ok(JsonConvert.SerializeObject(febFormData, Newtonsoft.Json.Formatting.Indented));
As you see, febFormData.Add("ReturnedData", ???); is the spot where I am stuck and dont really know what to do in order to get the dictionary to output the correct JSON format like I want.
Any help would be great!
update
Would this be how the class needs to look?
public class theOutput
{
public string name { get; set; }
public string devName { get; set; }
public List<string> ReturnedData { get; set; }
}
As suggested by #Panagiotis Kanavos you'd really be better off having .NET entity to match your JSON data. For example:
// propertyname attributes can be ignored if property names
// match the json data property names 1:1
[JsonObject]
public class MyClass
{
public MyClass()
{
ReturnedData = new List<ReturnedData>();
}
[JsonProperty(PropertyName = "name")]
public string Name { get; set; }
[JsonProperty(PropertyName = "devName")]
public string DevName { get; set; }
[JsonProperty(PropertyName = "ReturnedData")]
public List<ReturnedData> ReturnedData { get; set; }
}
[JsonObject]
public class ReturnedData
{
[JsonProperty(PropertyName = "level_heading")]
public string LevelHeading { get; set; }
[JsonProperty(PropertyName = "DeliverBestMedicalValue")]
public string DeliverBestMedicalValue { get; set; }
[JsonProperty(PropertyName = "level_question")]
public string LevelQuestion { get; set; }
}
This would make conversion to/from JSON that much easier.
[TestMethod]
public void TestSome()
{
string json = #"{
""name"": ""Bob Barker"",
""devName"": ""InformationServices"",
""ReturnedData"": [{
""level_heading"": ""blah1"",
""DeliverBestMedicalValue"": ""blah2"",
""level_question"": ""blah3""
}]
}";
var obj = JsonConvert.DeserializeObject<MyClass>(json);
Assert.IsTrue(JToken.DeepEquals(JObject.Parse(json), JObject.FromObject(obj)));
}
You can always generate stubs from you JSON data using e.g. http://json2csharp.com/
Here "live" .NET fiddle, too https://dotnetfiddle.net/9ACddp

Deserialize to object with custom object property

I have a class like so:
public class CareTaker
{
public int Id {get; set;}
public string name {get; set;}
public DateTime? DateTrained {get; set;}
public Certification Certification {get; set;}
public List<Certification> ExpiredCertifications {get; set;}
}
public class Certification
{
public int Id {get; set;}
}
and my JSON is like so:
{
"id": 1,
"name": "Dogtor",
"dateTrained": "01 Feb 2017",
"certification": 2,
"expiredCertifications": [1,5]
}
I know usually the JSON for Certification should really be like "certification": { "id": 2}, but, I don't have access to change the JSON so I have to figure out how to convert what I recieve ("certification": 2) to my object... Is there a way I can do this with either JavascriptSerializer or NewtonSoft please?
You could do something like this:
public class CareTaker
{
...
[NotMapped]
[JsonProperty(PropertyName = "certification"]
public int? CertificationId
{
get
{
return Certification?.Id;
}
set
{
Certification = new Certification { Id = value; }
}
}
[JsonIgnore]
public Certification Certification {get; set;}
...
}
To generate properly the classes, I would suggest copying the JSON and open the file where you want to store the classes and in visual studio go to EDIT->Paste Special->Paste JSON As Classes
then you would do something like this:
JavaScriptSerializer ser = new JavaScriptSerializer();
var jsonToClasses = ser.Deserialize<RootObject>(json);

Categories

Resources