I am new for json , as i am getting following json string.
i need following output 1,2,6,3,5,4 (get id object with comma separated) in asp.net with c#
[
{
"id":1,
"children":
[
{
"id":2,
"children" :
[
{"id":6},
{"id":3},
]
}
]
},
{
"id":5
},
{
"id":4
}
]
Code Behind work :
public class GetId
{
public string id { get; set; }
}
List<GetId> myDeserializedObjList = (List<GetId>)Newtonsoft.Json.JsonConvert.DeserializeObject(nestable_list_1_output.InnerText, typeof(List<GetId>));
for(int i=0; i < myDeserializedObjList.Count;i++)
{
string Id = myDeserializedObjList[i].id.ToString();
}
after implement this i get only 1,5,4 ...also i want children object Ids..
Thanks
Json to c# converters will not work great with this recursive definitions. In fact your class is simple
public class ID
{
public int id { get; set; }
public List<ID> children { get; set; }
}
Your json can now be in any depth. All you have to do is
var myDeserializedObjList = JsonConvert.DeserializeObject<List<ID>>(json);
You can now get the results recursively
PrintMyObject(myDeserializedObjList);
void PrintMyObject(List<ID> ids)
{
foreach (var id in ids)
{
Console.WriteLine(id.id);
if (id.children != null)
PrintMyObject(id.children);
}
}
To make the answer complete: This part is a Linq trick, to flatten your recursive data structure.
Func<List<ID>, IEnumerable<ID>> flattenList = null;
flattenList = l => l.SelectMany(x => new[] { x }.Concat( x.children==null
? Enumerable.Empty<ID>()
: flattenList(x.children)));
var flatList = flattenList(myDeserializedObjList).ToList();
Use json2csharp to generate correct class structure -
public class Child2
{
public int id { get; set; }
}
public class Child
{
public int id { get; set; }
public List<Child2> children { get; set; }
}
public class RootObject
{
public int id { get; set; }
public List<Child> children { get; set; }
}
Use this class RootObject to deserialize json response.
You should include children in your definition of the GetId class.
public class GetId
{
public int id { get; set; }
public List<GetId> children { get; set; }
}
Then when collecting the id's, you do it using a recursive call to make sure you get all ids in the lower structures.
private void CollectIdValues(List<GetId> list, List<int> ids){
foreach(GetId item in list){
ids.Add(item.id);
if(item.children != null){
CollectIdValues(item.children, ids);
}
}
}
List<GetId> myDeserializedObjList = Newtonsoft.Json.JsonConvert.DeserializeObject<List<GetId>>(jsonString));
List<int> allIds = new List<int>();
CollectIdValues(myDeserializedObjList, allIds);
Related
I have a below json, I want to loop the items inside the attribute CheckingUrls.
{
"Root": {
"Urls": {
"CheckingUrls": [
{
"API Management": {
"url": ".azure-api.net",
"displayurl": "*.azure-api.net"
},
"Log Analytics": {
"url": "1.ods.opinsights.azure.com",
"displayurl": "*.ods.opinsights.azure.com"
}
}
]
}
}
}
Here are the C# class
public class Root
{
Urls Urls { get; set; }
}
public class Urls
{
public List<CheckingUrls> CheckingUrls { get; set; }
}
public class CheckingUrls
{
[JsonProperty("API Management")]
public UrlDetails APIManagement { get; set; }
[JsonProperty("Log Analytics")]
public UrlDetails LogAnalytics { get; set; }
}
public class UrlDetails
{
[JsonProperty("url")]
public string url { get; set; }
[JsonProperty("displayurl")]
public string displayurl { get; set; }
}
I am trying to convert it into c# object using the below code
var content = File.ReadAllText(jsonstring);
var settings = JsonConvert.DeserializeObject<Root>(content);
I am getting APIManagement and LogAnalytics as properties in the result. Is it possible to get these as List, so that I can loop the contents without hardcoding the properties in code.
Why I need solution: We might add new child to CheckingUrls and we do not want to change the c# code everytime when we change JSON.
Use a C# Dictionary when you want to convert a JSON Object to C# when you don't have a concrete type. CheckingUrls is already an array, so you end up with
public List<Dictionary<string, UrlDetails>> CheckingUrls { get; set; }
The key of a Dictionary entry is the property name in the array element (like "API Management"), and the value is the object that contains the url and displayurl properties.
This eliminates the need for the CheckingUrls C# class.
If you want a List, you can create a CheckingUrls class
List<CheckingUrls> checkingUrlsList = JObject.Parse(json)
.SelectToken("Root.Urls.CheckingUrls")
.SelectMany(jo => ((JObject)jo).Properties()
.Select(p => new CheckingUrls
{
UrlName = p.Name,
UrlDetails = new UrlDetails
{
url = (string)p.Value["url"],
displayurl = (string)p.Value["displayurl"]
}
}
)).ToList();
public class CheckingUrls
{
public string UrlName { get; set; }
public UrlDetails UrlDetails { get; set; }
}
public class UrlDetails
{
public string url { get; set; }
public string displayurl { get; set; }
}
output ( in a json format)
[
{
"UrlName": "API Management",
"UrlDetails": {
"url": ".azure-api.net",
"displayurl": "*.azure-api.net"
}
},
{
"UrlName": "Log Analytics",
"UrlDetails": {
"url": "1.ods.opinsights.azure.com",
"displayurl": "*.ods.opinsights.azure.com"
}
}
]
but if you changed your mind to a Dictionary
Dictionary<string, UrlDetails> checkingUrlsDict = JObject.Parse(json)
.SelectToken("Root.Urls.CheckingUrls")
.Select(jo => jo.ToObject<Dictionary<string, UrlDetails>>())
.FirstOrDefault();
Good Morning, I'm falling on a problem that apparently should be easy but I cannot find a solution.
I have already red this and this posts, nothing helped.
I have an API, that returns data in JSON format with this schema, it has an indexer (I know it's idiotic, I didn't develop it) of the result before each object:
{
"total":2,
"0":{
"id_property":5028080,
"id_company":11719097,
....
},
"1":{
"id_property":4996958,
"id_company":11719097,
....
},
"status":"success"
}
I'm trying to deserialize it with System.Text.Json but it fails also with Newtonsoft.
According to the previous links I made a C# schema like this:
public class RootDTO
{
public int total { get; set; }
public Dictionary<string, PropertyDTO> Property { get; set; }
public string status { get; set; }
}
public class PropertyDTO
{
public int id { get; set; }
public string url { get; set; }
// OTHER PROPERTIES ...
}
I tried to deserialize it with the root Object and directly with the Dictionary in this way, either way it is failing. Null property in the first case, exception in the second case since it finds a "total" property not matching the schema.
RootDTO result = JsonSerializer.Deserialize<RootDTO>(content);
Dictionary<string, PropertyDTO> result = JsonSerializer.Deserialize<Dictionary<string, PropertyDTO>>(content);
Any idea on how to solve this apparently simple problem?
Many thanks everybody
Another thing I wasn't aware is that inside I have a SubObject with the same idiotic format
....
"galleries": [
{
"id": 4441310,
"0": {
"id": 146843541,
"url": "xxx",
"description": "",
"filename": "83732120220325094904.jpg",
"position": 1,
"url_big": "yyy",
"url_original": "kkk"
},
"1": {
"id": 146843542,
"url": "xxx",
"description": "",
"filename": "83732220220325094904.jpg",
"position": 2,
"url_big": "yyy",
"url_original": "kkk"
}
....
}
....
The issue there is that the objects are not represented by properties of the target type RootDTO.
You can handle that using the concept of overflow JSON: https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-handle-overflow?pivots=dotnet-6-0
public class RootDTO
{
public int total { get; set; }
public string status { get; set; }
//all the "overflowing" properties will be here
[System.Text.Json.Serialization.JsonExtensionData]
public Dictionary<string, JsonElement> Properties { get; set; }
}
RootDTO result = System.Text.Json.JsonSerializer.Deserialize<RootDTO>(json);
You can later deserialize the JsonElement in your PropertyDTO type.
You can get the values using a method like this where we deserialize to a dict of string keys and take any object so the code won't complain about the various types we have. Then further break it down into the specific fields you need.
EDIT - Try the code here
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
public class Program
{
public static void Main()
{
var json = #"{
""total"": 2,
""0"": {
""id_property"": 5028080,
""id_company"": 11719097
},
""1"": {
""id_property"": 4996958,
""id_company"": 11719097
},
""status"": ""success""
}";
var data = JsonSerializer.Deserialize<Dictionary<string,object>>(json);
foreach (var obj in data.Where(t => t.Key != "total" && t.Key != "status")) {
var dataObj = JsonSerializer.Deserialize<PropertyDTO>(obj.Value.ToString());
Console.WriteLine(dataObj.id_property);
Console.WriteLine(dataObj.id_company);
}
}
}
public class PropertyDTO
{
public int id_property { get; set; }
public int id_company { get; set; }
// OTHER PROPERTIES ...
}
the easiest way would be to use Newtonsoft.Json. You can try to use JsonExtensionData , but in this case you will have only a generic < string, object > dictionary. This code creates a typed dictionary
using Newtonsoft.Json;
var jsonParsed = JObject.Parse(json);
RootDTO rootDto = new RootDTO
{
total = (int)jsonParsed["total"],
properties = jsonParsed.Properties().Where(p => p.Value.Type is JTokenType.Object)
.ToDictionary(p =>p.Name, p=> p.Value.ToObject<PropertyDTO>());
status = (string)jsonParsed["status"]
}
classes
public class RootDTO
{
public int total { get; set; }
public Dictionary<string, PropertyDTO> properties { get; set; }
public string status { get; set; }
}
public class PropertyDTO
{
[JsonProperty("id_property")]
public int properyId { get; set; }
[JsonProperty("id_company")]
public int companyId { get; set; }
}
A work around can be the following:
Create another class that wraps desired values
public class IdioticWrapper<TValue> : IDictionary<string, JsonElement>
{
private IDictionary<string, TValue> desiredValues
= new Dictionary<string, TValue>();
private IDictionary<string, JsonElement> properties
= new Dictionary<string, JsonElement>();
public JsonElement this[string key]
{
get => this.properties[key];
set
{
// TODO: some checks like is null can deserialize ...
this.desiredValues[key] = JsonSerializer.Deserialize<TValue>(value.GetRawText());
}
}
// There are desired models
public IEnumerable<TValue> DesiredValues
=> this.desiredValues.Values;
public ICollection<string> Keys => this.properties.Keys;
public ICollection<JsonElement> Values => this.properties.Values;
public int Count => this.properties.Count;
public bool IsReadOnly => this.properties.IsReadOnly;
public void Add(string key, JsonElement value) => this.properties.Add(key, value);
public void Add(KeyValuePair<string, JsonElement> item) => this.properties.Add(item);
public void Clear() => this.properties.Clear();
public bool Contains(KeyValuePair<string, JsonElement> item) => properties.Contains(item);
public bool ContainsKey(string key) => this.properties.ContainsKey(key);
public void CopyTo(KeyValuePair<string, JsonElement>[] array, int arrayIndex) => this.properties.CopyTo(array, arrayIndex);
public IEnumerator<KeyValuePair<string, JsonElement>> GetEnumerator() => this.properties.GetEnumerator();
public bool Remove(string key) => this.properties.Remove(key);
public bool Remove(KeyValuePair<string, JsonElement> item) => this.properties.Remove(item);
public bool TryGetValue(string key, [MaybeNullWhen(false)] out JsonElement value) => this.properties.TryGetValue(key, out value);
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
}
2 use that wraper wehenever you need to wrap nested data of that kind
public class PropertyDTO
{
public int id_property { get; set; }
public int id_company { get; set; }
[JsonExtensionData]
public IdioticWrapper<object> properties { get; set; }
}
public class RootDTO
{
public int total { get; set; }
public string status { get; set; }
[JsonExtensionData]
public IdioticWrapper<PropertyDTO> properties { get; set; }
public IEnumerable<PropertyDTO> Values
=> this.properties.DesiredValues;
}
and at the end you shold get the correct result
var result = JsonSerializer.Deserialize<RootDTO>(jsonContent);
Console.WriteLine(result.total);
Console.WriteLine(result.status);
var values = result.Values;
// ... and so on
I created a class for a json object (not automatically).
However, I don't quite understand how to make the button object contain nameless arrays as in the example?
Example JSON (what the server expects to receive):
{
"one_time":false,
"buttons":[
[
{
"action":{
"type":"location",
"payload":"{\"button\": \"1\"}"
}
}
],
[
{
"action":{
"type":"open_app",
"app_id":6232540,
"owner_id":-157525928,
"hash":"123",
"label":"LiveWidget"
}
}
],
[
{
"action":{
"type":"vkpay",
"hash":"action=transfer-to-group&group_id=181108510&aid=10"
}
}
],
[
{
"action":{
"type":"text",
"payload":"{\"button\": \"1\"}",
"label":"Red"
},
"color":"negative"
},
{
"action":{
"type":"text",
"payload":"{\"button\": \"2\"}",
"label":"Green"
},
"color":"positive"
},
{
"action":{
"type":"text",
"payload":"{\"button\": \"2\"}",
"label":"Blue"
},
"color":"primary"
},
{
"action":{
"type":"text",
"payload":"{\"button\": \"2\"}",
"label":"White"
},
"color":"secondary"
}
]
]
}
Keyboard.cs (manually created class)
public class Keyboard
{
public bool one_time { get; set; }
public List<buttons> buttons { get; set; }
}
public class buttons
{
public action action { get; set; }
public string color { get; set; }
}
public class action
{
public string type { get; set; }
public string payload { get; set; }
public string label { get; set; }
}
I create an object like this:
var Keyboard_obj = new Keyboard()
{
one_time = false,
buttons = new List<buttons>()
{
new buttons()
{
action = new action()
{
type = "test1",
label = "class obj",
payload = "{\"button\": \"1\"}"
},
color = "negative"
},
new buttons()
{
action = new action()
{
type = "test2",
label = "class obj",
payload = "{\"button\": \"2\"}"
},
color = "positive"
}
}
};
How can I remake the class so that I get a JSON object like the example above?
You should use JsonSerializer
this code will give you a Json object like the example above:
var output = JsonConvert.SerializeObject(Keyboard_obj );
you can also create an object from Json:
Keyboard keyboard = JsonConvert.DeserializeObject<Keyboard>(output );
I can suggest you to try using dynamic objects
dynamic myObject = JsonConvert.DeserializeObject<dynamic>(input);
decimal Amount = Convert.ToDecimal(myObject.Amount);
string Message = myObject.Message;
If you take your JSON and use Visual studio (use paste as special option) or online tool to generate classes from the provided JSON then following classes will be generated.
Note - RootBoject.buttons Is an array or array instead of single collection.
public class Rootobject
{
public bool one_time { get; set; }
public Button[][] buttons { get; set; }
}
public class Button
{
public Action action { get; set; }
public string color { get; set; }
}
public class Action
{
public string type { get; set; }
public string payload { get; set; }
public int app_id { get; set; }
public int owner_id { get; set; }
public string hash { get; set; }
public string label { get; set; }
}
So with the provided class schema if you use JsonConvert to searialize the RootObject then you will get the required JSON.
I have an object which has a property which is list. Based on that list I want to filter property of it along with other properties of an object.
I have following object
{
Adult: 1,
Child: 0,
Infant: 0,
Origin: 'ABC',
Destination: 'XYZ',
DomesticFlightInfos: [{
FlightID: flightId1,
FareID: fareId1,
IsInbound: true
},
{
FlightID: flightId2,
FareID: fareId2,
IsInbound: false
}
]
};
I want following two objects
{
Adult: 1,
Child: 0,
Infant: 0,
Origin: 'ABC',
Destination: 'XYZ',
DomesticFlightInfos: [{
FlightID: flightId1,
FareID: fareId1,
IsInbound: true
}]
};
Adult: 1,
Child: 0,
Infant: 0,
Origin: 'ABC',
Destination: 'XYZ',
DomesticFlightInfos: [{
FlightID: flightId2,
FareID: fareId2,
IsInbound: false
}]
I was trying to do reservation.DomesticFlightInfos.Where(x => !x.IsInbound); which was wrong and got casting issue. What could be the best solution for it?
C# Object
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
new DomesticFlightReservation()
{
Adult = 1,
Child = 0,
Infant = 0,
Origin = "ABC",
Destination = "XYZ",
DomesticFlightInfos = new List<DomesticFlightInfo>(){
new DomesticFlightInfo{
FlightID= "flightId1",
FareID= "fareId1",
IsInbound= true
},
new DomesticFlightInfo {
FlightID= "flightId2",
FareID= "fareId2",
IsInbound= false
}
}
};
}
}
public class DomesticFlightReservation
{
public int Adult { get; set; } = 0;
public int Child { get; set; } = 0;
public int Infant { get; set; } = 0;
public string Origin { get; set; }
public string Destination { get; set; }
public List<DomesticFlightInfo> DomesticFlightInfos { get; set; }
}
public class DomesticFlightInfo
{
public string FlightID { get; set; }
public string FareID { get; set; }
// True for inbound, false for outbound
public bool IsInbound { get; set; }
}
Since you haven't provided C# object, assuming your C# objects to be defined as
public class DomesticFlightInfo
{
public string FlightID { get; set; }
public string FareID { get; set; }
public bool IsInbound { get; set; }
}
public class RootObject
{
public int Adult { get; set; }
public int Child { get; set; }
public int Infant { get; set; }
public string Origin { get; set; }
public string Destination { get; set; }
public List<DomesticFlightInfo> DomesticFlightInfos { get; set; }
}
If your intention is to separate the Inbounds and Outbound flights to separate groups, you could
var reservation = JsonConvert.DeserializeObject<RootObject>(str);
var flattenedReservation = new[]{reservation}.SelectMany(x=>x.DomesticFlightInfos
.GroupBy(v=>v.IsInbound)
.Select(c =>
{
x.DomesticFlightInfos = c.ToList();
return x;
}));
var jsonCollection = flattenedReservation.Select(x=> JsonConvert.SerializeObject(x,settings));
If your intention is to separate out each flight info into separate jsons, you could
var flattenedReservation = new[]{reservation}.SelectMany(x=>x.DomesticFlightInfos
.Select(c =>
{
x.DomesticFlightInfos = new List<DomesticFlightInfo>{c};
return x;
}));
var jsonCollection = flattenedReservation.Select(x=> JsonConvert.SerializeObject(x));
Output
If you have a list as a collection, you can use SelectMany
So, if you have a list
List<RootObject> rootObjects
then you can do this like flatten the list to get individual items:
rootObjects.SelectMany(x=> x.DomesticFlightInfos).Where(y => !y.IsInbound);
In json.net, how can I deserialize this json:
{
"items": {
"count": 1,
"data": [
{
...
},
...
],
}
}
To this C# class:
class MyData
{
[JsonProperty("items/data")] // this doesn't work
public List<object> Items { get; set; }
}
-
// Then this doesn't populate Items
MyData data = JsonConvert.DeserializeObject<MyData>(json);
Is there an elegant way of doing this with json.net?
I just thought of how I could do this:
var jObject = JObject.Parse(json);
jObject["items"] = jObject["items"]["data"];
MyData data = JsonConvert.DeserializeObject<MyData>(jObject.ToString());
Anyone have a better solution?
For populate items you should have this
public class Datum
{
}
public class Items
{
public int count { get; set; }
public List<Datum> data { get; set; }
}
public class RootObject
{
public Items items { get; set; }
}
and then use this:
MyData data = JsonConvert.DeserializeObject<RootObject>(json);