Deserializing json with dynamic property name - json

Similar question was asked here Serialize/Deserialize dynamic property name using JSON.NET. I am not able to make it work in my situation as below:
I have the following JSON
{
"notes": {
"data": [{
"book": {
"items": [{
"page": "page 1",
"comment": "Some notes"
},
{
"page": "page 1",
"comment": "Some notes"
}
]
}
},
{
"journal": {
"items": [{
"page": "page 1",
"comment": "Some notes"
},
{
"page": "page 1",
"comment": "Some notes"
}
]
}
},
{
"magazine": {
"items": [{
"page": "page 1",
"comment": "Some notes"
},
{
"page": "page 1",
"comment": "Some notes"
}
]
}
}
]
}
}
Created the following classes for JSON serialization:
public class TestParse
{
public Note Notes { get; set; }
}
public class Note
{
public IList<Data> Data { get; set; }
}
public class Data
{
public Source Source { get; set; }
}
[JsonConverter(typeof(MyConverter))]
public class Source
{
public IList<Items> Items { get; set; }
}
public class Items
{
public string Page { get; set; }
public string Comment { get; set; }
}
public class MyConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Source);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
{
var jo = JObject.Load(reader);
var req = new Data
{
Source = jo.ToObject<Source>()
};
return req;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var req = (Source)value;
var jo = new JObject(
new JObject(req.Items));
jo.WriteTo(writer);
}
}
}
I am still not able to deserialize "Source." Any pointer is appreciated.

In the other question you referenced, the dynamic key was determined by the value of another property in the same object. Hence, a converter was needed.
In your situation, you have dynamic keys, but they are not dependent on anything.
You don't really need a converter here; you can just use a Dictionary to handle the dynamic keys.
Change this line in your Note class:
public IList<Data> Data { get; set; }
to this:
public IList<IDictionary<string, Source>> Data { get; set; }
and remove the [JsonConverter] attribute from your Source class. Then it should work.
(You can also delete the Data class as it is not needed.)
Fiddle: https://dotnetfiddle.net/80lIRI

Related

How to prepare json or json array for api in .net core using httpclient

I want to prepare a json like below using c#. I want to use it for post api call. How can I do it?
{
"inputs": [
{
"person": {
"name": "xyz",
"country": "india",
"phone": "9999999999",
}
},
{
"person": {
"name": "abc",
"country": "india",
"phone": "8888888888",
}
}
]
}
If you want to bind json array from appsetting.json to class, you can use following code:
create three models
public class person
{
public string name { get; set; }
public string country { get; set; }
public string phone { get; set; }
}
public class inputs
{
public person person { get; set; }
}
public class conf
{
public inputs[] inputs { get; set; }
}
Inject them into container in program.cs(.Net 6)
builder.Services.Configure<conf>(builder.Configuration);
Then in your controller, Using Dependency Injection in the Constructor to Get the Value
public class HomeController : Controller
{
private readonly IOptions<conf> _option;
public HomeController(ILogger<HomeController> logger, IConfiguration configuration,IOptions<conf> option)
{
_option = option;
}
Finally, You can use model's properties to get the value from appsetting.json

How to extract only part of the JSON and de-serialize it in .netcore

I have .net core application , where an API is called through HTTPClient.
The response for that API in JSON format is as follows:
{
"ID": 25,
"Customer": "CustomerName",
"total": 100,
"details": [
{
"ItemId": "Item1",
"ItemName": "Name1",
"Price": "10"
},
{
"ItemId": "Item2",
"ItemName": "Name2",
"Price": "50"
},
{
"ItemId": "Item3",
"ItemName": "Name3",
"Price": "40"
}
]
}
I get this response from -- > var response = client.GetAsync(ApiPath).Result;
Now from the response variable I need details only for details like :
{
{
"ItemId": "Item1",
"Price": "10"
},
{
"ItemId": "Item2",
"Price": "50"
},
{
"ItemId": "Item3",
"Price": "40"
}
}
I have a DTO class like this :
public class ItemDetails
{
public string ItemId { get; set; }
public string Price { get; set; }
}
Can anyone help in extracting the details according to the DTO class from the main variable "response".
Many thanks!
Try this if you are using newtonsoft
var token = JObject.Parse(response);//load
var detailsToken = token.SelectToken("details");//select
var itemDetails = detailsToken.ToObject<ItemDetails[]>(); //cast to array
Only the properties that exist on ItemDetails will be mapped
You can deserialize the response into an object and take whatever you like from it.
Use the built-in JSON library in .net-core as following
using System.Text.Json;
using System.Text.Json.Serialization;
then make a Response classes to contain the Response values
public class ResponseObject
{
public int ID { get; set; }
public string Customer { get; set; }
[JsonPropertyName("total")]
public int Total { get; set; }
[JsonPropertyName("details")]
public ItemDetails[] Details { get; set; }
}
public class ItemDetails
{
public string ItemId { get; set; }
public string ItemName { get; set; }
public string Price { get; set; }
}
finally, deserialize and extract whatever you like as following
var o = JsonSerializer.Deserialize<ResponseObject>(response);
ItemDetails[] itemDetails= o.Details;

How to Serialize Collection to Json but with class name preceding each instance

I have the following Class Structure in my ASP.Net Core 3.1 application:
public class EmailModel
{
public string Subject { get; set; }
public BodyModel Body { get; set; }
public List<EmailAddress> ToRecipients { get; set; }
}
public class EmailAddress
{
public string Name { get; set; }
public string Address { get; set; }
}
which serializes as follows:
{
"subject": "tba",
"body": {
"contentType": "html",
"content": "the content"
},
"toRecipients": [
{
"name": "",
"address": "name1#example.com"
},
{
"name": "",
"address": "name2#example.com"
}
]
}
But what I need it to serialize to is the following (each emailAddress element is named):
{
"subject": "tba",
"body": {
"contentType": "html",
"content": "the content"
},
"toRecipients": [
{
"emailAddress": {
"name": "",
"address": "name1#example.com"
}
},
{
"emailAddress": {
"name": "",
"address": "name2#example.com"
}
}
]
}
How can I achieve this (am happy to use either System.Text.Json OR Newtonsoft, whichever is easier)
As advised by #Andy, consider just having a model which reflects Json, because it would be much more intuitive approach.
Otherwise, with Newtonsoft.Json you can customize serialization of elements of a collection using JsonPropertyAttribute attribute with ItemConverterType property. And implementing a custom JsonConverter class, like:
public class EmailModel
{
public string Subject { get; set; }
public BodyModel Body { get; set; }
[JsonProperty(ItemConverterType = typeof(NestingEmailAddressConverter))]
public List<EmailAddress> ToRecipients { get; set; }
}
public class NestingEmailAddressConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
JObject o = new JObject();
o.Add("emailAddress", JToken.FromObject(value));
o.WriteTo(writer);
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(EmailAddress);
}
public override bool CanRead => false;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
=> throw new NotImplementedException();
}
Called as Console.WriteLine(JsonConvert.SerializeObject(model, Formatting.Indented)); produces target Json.

how to send complex type from client side to server side

i have a page that needs to send complex data from client side into webmethod in asp.net mvc.
my data is :
{"tbl":[{"row":{"items":[{"name":"madrak1","val":"fdsfds"},{"name":"mahaleTahsil1","val":"fdsfds"},{"name":"reshte1","val":""},{"name":"start1","val":""},{"name":"end1","val":""}]}}]}
i need to have a class named table that put all the variables inside it.
my webmethod is :
public ActionResult SaveDetailedInfo(List<rrow> tbl)
{
return Json(new { status = "Success", message = "Success" });
}
Your C# classes should look something like:
public class Item
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("val")]
public string Val { get; set; }
}
public class Row
{
[JsonProperty("items")]
public IList<Item> Items { get; set; }
}
public class Tbl
{
[JsonProperty("row")]
public Row Row { get; set; }
}
public class Table
{
[JsonProperty("tbl")]
public IList<Tbl> Tbl { get; set; }
}
And your MVC method:
public ActionResult SaveDetailedInfo(Table table)
{
return Json(new { status = "Success", message = "Success" });
}
So sending data from your front end...
var table = {
"tbl": [{
"row": {
"items": [{
"name": "madrak1",
"val": "fdsfds"
}, {
"name": "mahaleTahsil1",
"val": "fdsfds"
}, {
"name": "reshte1",
"val": ""
}, {
"name": "start1",
"val": ""
}, {
"name": "end1",
"val": ""
}]
}
}]
};
var xhr = new XMLHttpRequest();
xhr.open('POST', '/Home/SaveDetailedInfo', true);
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
// send the collected data as JSON
xhr.send(JSON.stringify(table));
Should result in...
PS. There is an easy way to convert your json objects into C# classes

Deserialize complex object with Json

How would I deserialize this with JSON.NET. I keep getting a "cannot perform binding on a null reference" exception. Here is the code, and the JSON output below:
var json = client.DownloadString("https://myapp.tpondemand.com/api/v1/UserStories?take=999&include=[Tasks[Id,Name,TimeSpent]]&format=json");
dynamic output = Newtonsoft.Json.JsonConvert.DeserializeObject(json);
string nemo = output.items[1].Id[0];
Console.ReadLine();
{
"Items": [
{
"Id": 395,
"Tasks": {
"Items": []
}
},
{
"Id": 394,
"Tasks": {
"Items": []
}
},
{
"Id": 393,
"Tasks": {
"Items": []
}
},
{
"Id": 336,
"Tasks": {
"Items": []
}
},
}
]
If you know Json format just create datacontracts and deserialize them.
For example
[DataContract]
public class ItemJson
{
[DataMember]
public string Id { get; set; }
[DataMember]
public List<TaskJson> Tasks { get; set; }
}
[DataContract]
public class TaskJson
{
[DataMember]
public List<ItemJson> Items{ get; set; }
}