Convert Dynamic Json to Something more Concrete - c#

How can I deserialize the JSON below to a C# array or something more manageable.
{
"data": [
{
"PropertyName": [
{
"Key1": "test",
"Key2": "afafa"
},
{
"Key1": "test",
"Key2": "afafa"
}
],
"PropertyName2": [
{
"Key1": "test",
"Key2": "afafa"
},
{
"Key1": "test",
"Key2": "afafa"
}
]
}
]
}
It comes in as a dynamic parameter like this:
public IActionResult SAve([FromBody] dynamic mapping)
I normally would make this a concrete class but "PropertyName" will change to different names, so I need something flexible. The contents of it can be concrete as it is just two properties.
I am thinking that it could be like a dictionary.
Dictionary<string, ConcreteClass>()
I just don't know how to get it into that form.
Edit.
I have gone ahead and did the suggestion but it does not work
{{
"data": [
{
"propertyName": [
{
"key1": 1,
"key2": "1"
},
{
"key1": 2,
"key2": "2"
}
]
}
]
}}
I tried to convert like this
var ddd = JsonConvert.DeserializeObject<List<MappingDto>>(mapping.data.ToString());
this makes an empty object in the array. If I don't have it wrapped in a collection then I get a different error
public class MappingDto
{
public List<Dictionary<string, List<Item>>> Items { get; set; }
}
public class Items
{
public string Key1{ get; set; }
public string Key2{ get; set; }
}

For this JSON, a concrete class structure that handles the dynamic property names as you described would look like this:
public class MappingDto
{
public List<Dictionary<string, List<Item>>> Data { get; set; }
}
public class Item
{
public string Key1 { get; set; }
public string Key2 { get; set; }
}
Be sure to update your method signature to use the new class instead of dynamic:
public IActionResult SAve([FromBody] MappingDto mapping)
You can then access the data like this (for example):
foreach (var dict in mapping.Data)
{
foreach (var kvp in dict)
{
Debug.WriteLine(kvp.Key);
foreach (var item in kvp.Value)
{
Debug.WriteLine(" Key1: " + item.Key1);
Debug.WriteLine(" Key2: " + item.Key2);
}
}
}
Fiddle: https://dotnetfiddle.net/OGylPh

Related

Get specific data from a JSON

Suppose there is a JSON structure like below
{
"v": "2021",
"Outeritems": [
{
"items": [
{
"c": "r",
"KeyOne": "DataOne",
"KeyTwo": "DataTwo",
"items": [
{
"c": "r",
"KeyOne": "DataThree",
"KeyTwo": "DataFour",
"v": "F",
"h": "N",
"l": "N:"
},
{
"c": "r",
"KeyOne": "DataFive",
"KeyTwo": "DataSix",
"v": "T"
}
]
}
]
}
]
}
How can I read all KeyOne and its corresponding KeyTwo(line below KeyOne) using linq or some method. They may be nested in any of items array. We need to get all such properties as a dictionary or key value pair like that. Thanks for help.
Well instead commenting out, lets build an aprox answer.
Actually the better aproach is deserialize the JSON to a class with only the relevant properties, instead trying to use all the JSON structure.
Like:
private class Item
{
[JsonProperty("KeyOne")]
public string KeyOne { get; set; }
[JsonProperty("KeyTwo")]
public string KeyTwo { get; set; }
[JsonProperty("items")]
public List<Item> Items { get; set; }
}
private class Outeritem
{
[JsonProperty("items")]
public List<Item> Items { get; set; }
}
private class Root
{
[JsonProperty("Outeritems")]
public List<Outeritem> Outeritems { get; set; }
}
Then deserialize like:
Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(myJsonResponse);
Then for transverse the tree you can use a recursive aproach (just because a JSON string is a rather finite structure, not a good aproach in ALL cases)
List<string> KeyOneValues = new List<string>();
List<string> KeyTwoValues = new List<string>();
trasverseNode(List<Item> item)
{
if (item.KeyOne != null) KeyOneValues.Add(item.KeyOne);
if (item.KeyTwo != null) KeyTwoValues.Add(item.KeyTwo);
foreach (Item child in item.Items)
{
trasverseNode(child); //<-- recursive
}
}

Serialize Json object with properties dinamycally with dictionary

I need to serialize a response of an object with a dictionary dynamically
left the json examples
I am trying to serialize this response object (request_validator) in a c# class
but this is not working
someone who can help me please, any ideas?
{
"person": {
"testing": "CC",
"simple": "1234545",
"errorNames": {
"id": "655789",
"error": "simple"
},
"errorColor": {
"id": "2",
"error": "error color"
}
}
}
{
"request_validator": [
{
"person.errorNames": [
"error names"
],
"person.errorColor": [
"error color"
]
}
]
}
public class DeserializeResponse{
public Dictionary<string, List<string>> request_validator { get; set; }
}
var error = JsonConvert.DeserializeObject<List<DeserializeResponse>>(content);
You can use Newtonsoft.Json library to get all properties from string array into dictionary
in this case you just need to point to the searched level
using Newtonsoft.Json.Linq;
...
JObject validator = JObject.Parse(content);
IJEnumerable<JToken> validatorTokens = validator.SelectTokens("request_validator")?.Values();
Dictionary<string, List<string>> errors = new Dictionary<string, List<string>>();
if (validatorTokens != null)
{
foreach (JProperty prop in validatorTokens.Values())
{
if (!errors.ContainsKey(prop.Name))
{
errors.Add(prop.Name, new List<string>());
}
errors[prop.Name].Add(prop.Value?.ToString());
}
}
public class DeserializeResponse
{
[JsonPropertyName("request_validator")]
public RequestValidator[] RequestValidator { get; set; }
}
public class RequestValidator
{
[JsonPropertyName("person.errorNames")]
public string[] PersonErrorNames { get; set; }
[JsonPropertyName("person.errorColor")]
public string[] PersonErrorColor { get; set; }
}
...
var error = JsonSerializer.Deserialize<DeserializeResponse>(content);

Json serialization of a nested Dictionary returns { "key": "key1", "value": "value1" }

I'm currently working on a webservice, and I have this behavior that I haven't encountered until today. Here's the class I'm returning:
public class Block
{
public int order { get; set; }
public string title { get; set; }
public Dictionary<string, object> attributes { get; set; }
}
attributes can contain any kind of value: simple type, object, array, etc.
And when I return a Block object through my webservice, here's what I get:
{
"order": 1,
"attributes": [
{
"Key": "key1",
"Value": "value1"
},
{
"Key": "key2",
"Value": "value2"
}
],
"title": "Title"
}
Does anyone know why I'm not simply getting a "key1": "value1" output?
First of all your JSON is not valid, please be aware there are no , after "order": 1 this line.
After this correction you can change your class structure like this
public class Attribute
{
public string Key { get; set; }
public object Value { get; set; }
}
public class Block
{
public int order { get; set; }
public List<Attribute> attributes { get; set; }
public string title { get; set; }
}
this way you will be able to deserialize your JSON, I used simply this website https://json2csharp.com/ for converting your JSON into C# class
As for usage you can do .FirstOrDefault(x=>x.Key=="key1") to get whichever data you want, or if you will process all the list one by one you can simply do attributes.Count
When I do
var x = new Class
{
order = 1,
title = "Title",
attributes = new Dictionary<string, object>
{
{ "key1", "value1" },
{ "key2", "value2" }
}
};
var json = JsonConvert.SerializeObject(x);
Console.WriteLine(json);
I get
{"order":1,"title":"Title","attributes":{"key1":"value1","key2":"value2"}}
Do you have code that serializes your data or does ASP.NET do it for you?

Not getting result when deserializing json using DataContractJsonSerializer

I have following json:
{
"Australia": {
"count": 2,
"records": {
"File1.ppt": {
"id": "123456789"
},
"File2.doc": {
"id": "987654321"
}
}
},
"PDFs.zip": {
"count": 0,
"records": {}
},
"Peru": {
"count": 2,
"records": {
"File3.PPT": {
"id": "897456123"
},
"File4.PPT": {
"id": "123546789"
}
}
},
"total count": 4
}
and to deserialize the above json I have defined some classes so that I can use these classes while deserializing my json into objects and below are the classes:
namespace GEO_Batch_Creation
{
[DataContract]
class BhpIdJson
{
[DataMember(Name = "objects")]
public Dictionary<string, Country[]> Countries { get; set; }
[DataMember(Name = "total count")]
public int TotalCount { get; set; }
}
[DataContract]
class Country
{
[DataMember(Name = "count")]
public int Count { get; set; }
[DataMember(Name = "records")]
public Dictionary<string, Record> Records { get; set; }
}
[DataContract]
class Record
{
[DataMember(Name = "filename")]
public string FileName { get; set; }
[DataMember(Name = "id")]
public Dictionary<string, string> BhpId { get; set; }
}
}
But when I use following code to deserialize the json I am getting only total count.
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(json)))
{
// Deserialization from JSON
DataContractJsonSerializer deserializer = new DataContractJsonSerializer(typeof(BhpIdJson));
BhpIdJson bsObj2 = (BhpIdJson)deserializer.ReadObject(ms);
}
Please suggest me where I am doing mistake.
I don't think that this JSON is in correct format. I don't know if you got this from somewhere or made for yourself, but if the last one I recommend you to change the structure.
Even in C# you cant realy create a class that has the objects and the count of the object in the same List or Array etc.
Based on your class your JSON yhould look like this:
{
"objects": [
{
"name": "Australia",
"count": 2,
"records": [
{
"fileName": "File1.ppt",
"id": "123456789"
},
{
"fileName": "File2.doc",
"id": "987654321"
}
]
}
],
"total count": 4
}
As you can see you have to add Name or something to your Country class. I hope it helped.
Edit:
You can create a list like I mentioned above but it's not a good practice I think.

JSON Object from C#

I am trying to acheive below JSON Object from c# code
{
"Animals": {
"name": "Animals",
"data": [
[
"Cows",
2
],
[
"Sheep",
3
]
]
},
"Fruits": {
"name": "Fruits",
"data": [
[
"Apples",
5
],
[
"Oranges",
7
],
[
"Bananas",
2
]
]
},
"Cars": {
"name": "Cars",
"data": [
[
"Toyota",
1
],
[
"Volkswagen",
2
],
[
"Opel",
5
]
]
}
}
I tried json2C# link and it gave me this class structure
public class Animals
{
public string name { get; set; }
public List<List<object>> data { get; set; }
}
public class Fruits
{
public string name { get; set; }
public List<List<object>> data { get; set; }
}
public class Cars
{
public string name { get; set; }
public List<List<object>> data { get; set; }
}
public class RootObject
{
public Animals Animals { get; set; }
public Fruits Fruits { get; set; }
public Cars Cars { get; set; }
}
My first problem is the classes generated by code is static (Animals,Fruits,Cars) in reality it could be more and less it is category and it may be some new categories so every time I need to create a new class for each category? how can I handle this?
Second how I populate from these classes the same structure.
Please bear with me as I am very beginner level programmer.
Try this. Create a new console application. You will need the JSON.NET library.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
namespace ConsoleApplication7
{
class Item : List<object>
{
public Item()
{
this.Add(""); // for name;
this.Add(0); // for value;
}
[JsonIgnore]
public string Name { get { return this[0].ToString(); } set { this[0] = value; } }
[JsonIgnore]
public int Value { get { return (int)this[1]; } set { this[1] = value; } }
}
class Category
{
public string name { get; set; }
public List<Item> data { get; set; }
public Category()
{
this.data = new List<Item>();
}
}
class Program
{
static void Main(string[] args)
{
var all = new Dictionary<string, Category>
{
{
"Animals", new Category()
{
name = "Animals",
data =
new List<Item>()
{
new Item() {Name = "Cows", Value = 2},
new Item() {Name = "Sheep", Value = 3}
}
}
//include your other items here
}
};
Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(all));
Console.ReadLine();
}
}
}
You don't need separate Animals, Fruits, etc. classes. They can be merged.
public class Category
{
public string name { get; set; }
public List<List<object>> data { get; set; }
}
And since the list of items in the root object can change, you should use a Dictionary<string, Category> instead of the RootObject class you had generated. Your JSON is not valid, (test it with http://jsonlint.com/), but this produces something like the first part of your example:
var dict = new Dictionary<string, Category>
{
{ "Animals", new Category
{
name = "Animals",
data = new List<List<object>>
{
new List<object> { "Cows", 2 },
new List<object> { "Sheep", 3 }
}
}
},
};
string serialized = JsonConvert.SerializeObject(dict, Formatting.Indented);
Produces the following (I'm using Json.NET for the serialization here). The other types would be similar. (see Object and Collection Initializers for more info on the list and dictionary initialization syntax I used, if you're unfamiliar with it; basically just shortcuts for their Add methods)
{
"Animals": {
"name": "Animals",
"data": [
[
"Cows",
2
],
[
"Sheep",
3
]
]
}
}
If you have a choice of what the data types should be, I think it'd be better to replace the List<object> with a class something like this, to be more clear:
public class Item
{
public string name { get; set; }
public int quantity { get; set; }
}
Install the JSON.NET library.
Then with the classes that were created:
string jsonStr = "{'Animals': {name: 'Animals', data: [['Cows', 2], ['Sheep', 3] ] },'Fruits': { name: 'Fruits', data: [['Apples', 5], ['Oranges', 7], ['Bananas', 2] ] }, 'Cars': { name: 'Cars', data: [ ['Toyota', 1], ['Volkswagen', 2], ['Opel', 5] ] } }";
RootObject Myobj = Newtonsoft.Json.JsonConvert.DeserializeObject<RootObject>(jsonStr);

Categories