I have the following JSON object (the shape of the object will vary hence use of dynamic):
{
"mba$maccType": [{
"class": {
"id": 1057,
"intlId": "cacc"
},
"classA": false,
"endDate": "4712-12-31T00:00:00",
"histStatus": {
"id": 5,
"intlId": "valid"
},
"objClassif": {
"id": 74,
"intlId": "mba$macc_type"
},
"secUser": {
"id": 2
},
"startDate": "2018-12-01T00:00:00",
"timestamp": "2020-01-18T07:29:21"
}
]
}
I'm using Newtonsoft.Json to parse as follows:
dynamic dyn = JObject.Parse(json);
My problem is, I'm unable to reference any dynamic properties because the parent property containing the $ gives a syntax error:
Console.WriteLine(dyn.mba$maccType);
How can I get to the value of "class.intlId" (i.e. "cacc")?
You can parse your JSON to JObject instead of dynamic type and access its items by key. Like get the first item from mba$maccType (since it's an array), then access a class token and intlId value from it
var jObject = JObject.Parse(json);
var firstItem = jObject["mba$maccType"]?.FirstOrDefault();
var result = firstItem?["class"]?["intlId"]?.ToString(); // returns "cacc"
Supposing that the only dynamic part of your JSON structure are the property names on the outer object, you can deserialize this JSON to a Dictionary<string, List<T>>. The benefit of doing this is that you would have clearly defined types for almost everything that's deserialized.
// type definitions
class ClassRecord
{
public int id { get; set; }
public string intlId { get; set; }
}
class Item
{
public ClassRecord #class { get; set; }
public bool classA { get; set; }
// etc.
}
// deserialize
var obj = JsonConvert.DeserializeObject<Dictionary<string, List<Item>>>(json);
Console.WriteLine(obj["mba$maccType"][0].#class.id); // 1057
Related
I have a json array as ahown below with two keys "entities" and "TotalResults". within entities there is "Fields". I want to obtain the elements within "Fields" i.e, "name" and "values". so that i can iterate over the Fields to find the matching name and it's respective value. I have tried most of the solutions out there, nothing seems to give the result i want. Any help would be admired.
below is the Json array :
{"entities": [
{
"Fields": [
{
"Name": "test-id",
"values": [
{
"value": "268"
}
]
},
{
"Name": "os-config",
"values": [
{}
]
},
{
"Name": "pc-mobile-host",
"values": [
{}
]
}
}
],
"TotalResults": 2}
Code i tried are below (only two are mentioned though i tried lots of other methods) :
1.
Dictionary<string,object> Result= JsonConvert.DeserializeObject<Dictionary<string,object>>(json);
2.
public class Fields
{
[JsonProperty("values")]
public IList<object> values { get; set; }
[JsonProperty("Name")]
public string Name { get; set; }
}
public class RootObject
{
public IList<Fields> Fields { get; set; }
}
var Result = JsonConvert.DeserializeObject<RootObject>(json);
First (using Newtonsoft.Json) parse json to JObject and then you can access and iterate Fields objects using SelectToken.
There was still error in your JSON while writing this answer so I've modified it to be valid
var json = #"{""entities"":[{""Fields"":[{""Name"":""test-id"",""values"":[{""value"":""268""}]},{""Name"":""os-config"",""values"":[{}]},{""Name"":""pc-mobile-host"",""values"":[{}]}]}],""TotalResults"":2}";
var jObject = JObject.Parse(json);
var fields = jObject.SelectToken("$..Fields").ToList();
foreach (var field in fields)
{
}
I am selecting a json object as follows:
var gridRenderer = json.SelectToken("$..gridRenderer").FirstOrDefault();
The line above gives the following subset of the JSON shown at the end of the question:
{
"items": [
{
"gridVideoRenderer": { } // Many properties omitted.
},
// Other entries omitted.
Located at the path:
contents.twoColumnBrowseResultsRenderer.tabs[0].tabRenderer.content.sectionListRenderer.contents[0].itemSectionRenderer.contents[0].gridRenderer
As you can see above there is a lot of data. I want to cast this to typed object with a sub set of properties:
var ee = gridRenderer.Cast<GridRenderSection>();
First I just wanted to get an array with objects with the videoid. I have following classes:
[JsonObject("gridRenderSection")]
public class GridRenderSection
{
[JsonProperty("items")]
public List<GridVideoRenderer> Items{ get; set; }
}
public class GridVideoRenderer
{
[JsonProperty("videoId")]
public string VideoId { get; set; }
}
But I get following error:
"Unable to cast object of type 'Newtonsoft.Json.Linq.JArray' to type 'GridRenderSection'."
Normally you can cast subset of types objects, is that not possible with the Cast function, or am I missing something here?
Sample code (notice you can see json on the link provided in sample code or below):
var jsonStr = string.Empty;
using (WebClient client = new WebClient())
{
jsonStr = client.DownloadString("https://srv-file2.gofile.io/download/J1iBAd/json1.json");
}
var json = JObject.Parse(jsonStr);
var gridRenderer = json.SelectToken("$..gridRenderer").FirstOrDefault();
var ee = gridRenderer.Cast<GridRenderSection>();
JSON:
{
"contents": {
"twoColumnBrowseResultsRenderer": {
"tabs": [
{
"tabRenderer": {
"title": "Videoer",
"selected": true,
"content": {
"sectionListRenderer": {
"contents": [
{
"itemSectionRenderer": {
"contents": [
{
"gridRenderer": {
"items": [
{
"gridVideoRenderer": {
"videoId": "lzSlEtuHgAU"
}
},
{
"gridVideoRenderer": {
"videoId": "F5Opl1llzWw"
}
}
]
}
}
]
}
}
]
}
}
}
}
]
}
}
}
You have a few problems here:
Your query json.SelectToken("$..gridRenderer") is returning a single JToken corresponding to the following JSON object:
{
"items": [
{
"gridVideoRenderer": {
"videoId": "lzSlEtuHgAU"
}
},
{
"gridVideoRenderer": {
"videoId": "F5Opl1llzWw"
}
}
]
}
You are trying to cast this to a GridRenderSection, but JToken has no explicit or implicit type conversion to arbitrary types -- only to simple IConvertible types. Instead you will need to deserialize to GridRenderSection using ToObject<GridRenderSection>():
var ee = gridRenderer.ToObject<GridRenderSection>();
You are calling FirstOrDefault() on the return from SelectToken():
json.SelectToken("$..gridRenderer").FirstOrDefault();
However, SelectToken() already returns a single JToken that matches the query, in this case a JObject. (If there is more than one match, SelectToken() throws an exception.) Later, when you do .FirstOrDefault() you are grabbing the first property of the object and trying to deserialize that single property into your data model, which is wrong.
Generally, if you are calling SelectToken() there is no need to call .FirstOrDefault(); it's more commonly applied to SelectTokens() when there might be many matches and only the first is needed.
Your data model does not match your JSON. videoId is nested inside a container object gridVideoRenderer which needs to be modeled like so:
public class GridRenderSection
{
[JsonProperty("items")]
public List<GridRenderSectionItem> Items{ get; set; }
}
public class GridRenderSectionItem
{
public GridVideoRenderer gridVideoRenderer { get; set; }
}
public class GridVideoRenderer
{
[JsonProperty("videoId")]
public string VideoId { get; set; }
}
Incidentally, if all you need are the videoId values, you could use the following SelectTokens() query to extract them directly:
var videoIds = json.SelectTokens("$..gridRenderer.items[*].gridVideoRenderer.videoId")
.Select(t => t.ToString())
.ToList();
Or if you want just a list of GridVideoRenderer objects:
var renderers = json.SelectTokens("$..gridRenderer.items[*].gridVideoRenderer")
.Select(t => t.ToObject<GridVideoRenderer>())
.ToList();
Demo fixed fiddle here.
How do I ignore duplicate fields?
For example I have this raw json { "Value": 3, "Name": "Test", "value": "irrelevant" }
I would like to ignore value because my target type has public int Value { get; set; }
We have this kind of issue on most of the data from the client side views. In asp.net core, how do we instruct the json serializer to use the property that matches the type in the target?
Cheers,
Unfortunately, this isn't possible.
Assuming this JSON:
{
"Value": 3,
"Name": "Test",
"value": "irrelevant"
}
And this class:
public class MyClass
{
public string Value { get; set; }
public string Name { get; set; }
}
JSON.NET will deserialize as follows:
Value = 3
Name = "Test"
Value = "irrelevant"
The deserializer doesn't have a "state" so it doesn't care if Value was previously deserialized; it simply assigns the properties as it goes.
The reason you're getting an error is that your class defines Value as an int. This results in the deserializer executing:
Value = 3
Name = "Test"
Value = "irrelevant" <--- throw exception because int can't be set to a string value.
Maybe someone knows better version to resolve my problem?
Have next json:
[
{
"name":{
"IsEmpty":false,
"X":-10.5,
"Y":2.47
},
"password":"pas"
},
{
"name":{
"IsEmpty":false,
"X":-10.5,
"Y":2.47
},
"password":"pas"
},
{
"name":{
"IsEmpty":false,
"X":-10.5,
"Y":2.47
},
"password":"pas"
}
]
I want parse elements from json to my classes:
public class Name
{
public bool IsEmpty { get; set; }
public double X { get; set; }
public double Y { get; set; }
}
public class RootObject
{
public List<Name> name { get; set; }
public string password { get; set; }
}
......
dynamic res = JsonConvert.DeserializeObject<RootObject[]>(result1);
Variable result1 is my json object.
And exeption, what I have:
Cannot deserialize the current JSON object (e.g. {"name":"value"})
into type 'client_app.MainPage+RootObject[]' because the type requires
a JSON array (e.g. [1,2,3]) to deserialize correctly. To fix this
error either change the JSON to a JSON array (e.g. [1,2,3]) or change
the deserialized type so that it is a normal .NET type (e.g. not a
primitive type like integer, not a collection type like an array or
List) that can be deserialized from a JSON object.
JsonObjectAttribute can also be added to the type to force it to
deserialize from a JSON object. Path 'name', line 1, position 8.
The problem resides in the mapping between your JSon string and your root object. I think that this is what causes the problem:
"IsEmpty":false
When deserializing your object the JSon converter waits for the IsEmpty property to be of type bool.
Which is not the case since its type is List
So your root class should be like this:
public class RootObject
{
public Name name { get; set; }
public string password { get; set; }
}
Please try like this:
var res = JsonConvert.DeserializeObject<List<RootObject>>(result1);
This is the set of classes you need to deserialize
public class Name
{
public bool IsEmpty { get; set; }
public double X { get; set; }
public double Y { get; set; }
}
public class Item
{
public Name name { get; set; }
public string password { get; set; }
}
then
var items = Newtonsoft.Json.JsonConvert.DeserializeObject<Item[]>(json);
var ds = new DataContractJsonSerializer(typeof(RootObject[]));
var msnew = new MemoryStream(Encoding.UTF8.GetBytes(MyJsonString));
RootObject[] items = (RootObject[])ds.ReadObject(msnew);
This resolve my problem
Your Name class has the property of IsEmpty as a List of bools.
So you Json should be:
[
{
"name": {
"IsEmpty": [
false
],
"X": -10.5,
"Y": 2.47
},
"password": "pas"
},
{
"name": {
"IsEmpty": [
false
],
"X": -10.5,
"Y": 2.47
},
"password": "pas"
},
{
"name": {
"IsEmpty": [
false
],
"X": -10.5,
"Y": 2.47
},
"password": "pas"
}
]
Note the sqaure brackets on the value of IsEmpty, which signifies the value is in a collection. if you want to assign more than one value then you can add more using:
"IsEmpty": [ false, true ]
I have Json string like below
{
"JsonValues":{
"id": "MyID",
"values": {
"value1":{
"id": "100",
"diaplayName": "MyValue1"
},
"value2":{
"id": "200",
"diaplayName": "MyValue2"
}
}
}
}
I want to convert Json string to below classes
class ValueSet
{
[JsonProperty("id")]
public string id
{
get;
set;
}
[JsonProperty("values")]
public List<Value> values
{
get;
set;
}
}
class Value
{
public string id
{
get;
set;
}
public string DiaplayName
{
get;
set;
}
}
My deserialization code is
JavaScriptSerializer js = new JavaScriptSerializer();
StreamReader sr = new StreamReader(#"ValueSetJsonString.txt");
string jsonString = sr.ReadToEnd();
var items = JsonConvert.DeserializeObject<ValueSet>(jsonString);
But I am getting null values after serialization, How i can solve this?
As others have already pointed out, the reason you are not getting the results you expect is because your JSON does not match the class structure that you are trying to deserialize into. You either need to change your JSON or change your classes. Since others have already shown how to change the JSON, I will take the opposite approach here.
To match the JSON you posted in your question, your classes should be defined like those below. Notice I've made the following changes:
I added a Wrapper class corresponding to the outer object in your JSON.
I changed the Values property of the ValueSet class from a List<Value> to a Dictionary<string, Value> since the values property in your JSON contains an object, not an array.
I added some additional [JsonProperty] attributes to match the property names in your JSON objects.
Class definitions:
class Wrapper
{
[JsonProperty("JsonValues")]
public ValueSet ValueSet { get; set; }
}
class ValueSet
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("values")]
public Dictionary<string, Value> Values { get; set; }
}
class Value
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("diaplayName")]
public string DisplayName { get; set; }
}
You need to deserialize into the Wrapper class, not the ValueSet class. You can then get the ValueSet from the Wrapper.
var valueSet = JsonConvert.DeserializeObject<Wrapper>(jsonString).ValueSet;
Here is a working program to demonstrate:
class Program
{
static void Main(string[] args)
{
string jsonString = #"
{
""JsonValues"": {
""id"": ""MyID"",
""values"": {
""value1"": {
""id"": ""100"",
""diaplayName"": ""MyValue1""
},
""value2"": {
""id"": ""200"",
""diaplayName"": ""MyValue2""
}
}
}
}";
var valueSet = JsonConvert.DeserializeObject<Wrapper>(jsonString).ValueSet;
Console.WriteLine("id: " + valueSet.Id);
foreach (KeyValuePair<string, Value> kvp in valueSet.Values)
{
Console.WriteLine(kvp.Key + " id: " + kvp.Value.Id);
Console.WriteLine(kvp.Key + " name: " + kvp.Value.DisplayName);
}
}
}
And here is the output:
id: MyID
value1 id: 100
value1 name: MyValue1
value2 id: 200
value2 name: MyValue2
http://json2csharp.com/
I found the above link incredibly helpful as it corrected my C# classes by generating them from the JSON that was actually returned.
Then I called :
JsonConvert.DeserializeObject<RootObject>(jsonString);
and everything worked as expected.
Did you check this line works perfectly & your string have value in it ?
string jsonString = sr.ReadToEnd();
if yes, try this code for last line:
ValueSet items = JsonConvert.DeserializeObject<ValueSet>(jsonString);
or if you have an array of json you can use list like this :
List<ValueSet> items = JsonConvert.DeserializeObject<List<ValueSet>>(jsonString);
good luck
Your data structure and your JSON do not match.
Your JSON is this:
{
"JsonValues":{
"id": "MyID",
...
}
}
But the data structure you try to serialize it to is this:
class ValueSet
{
[JsonProperty("id")]
public string id
{
get;
set;
}
...
}
You are skipping a step: Your JSON is a class that has one property named JsonValues, which has an object of your ValueSet data structure as value.
Also inside your class your JSON is this:
"values": { ... }
Your data structure is this:
[JsonProperty("values")]
public List<Value> values
{
get;
set;
}
Note that { .. } in JSON defines an object, where as [ .. ] defines an array. So according to your JSON you don't have a bunch of values, but you have one values object with the properties value1 and value2 of type Value.
Since the deserializer expects an array but gets an object instead, it does the least non-destructive (Exception) thing it could do: skip the value. Your property values remains with it's default value: null.
If you can: Adjust your JSON. The following would match your data structure and is most likely what you actually want:
{
"id": "MyID",
"values": [
{
"id": "100",
"diaplayName": "MyValue1"
}, {
"id": "200",
"diaplayName": "MyValue2"
}
]
}
Json Convert To C# Class = https://json2csharp.com/json-to-csharp
after the schema comes out
WebClient client = new WebClient();
client.Encoding = Encoding.UTF8;
string myJSON = client.DownloadString("http://xxx/xx/xx.json");
var valueSet = JsonConvert.DeserializeObject<Root>(myJSON);
The biggest one of our mistakes is that we can't match the class structure with json.
This connection will do the process automatically. You will code it later ;) = https://json2csharp.com/json-to-csharp
that's it.
you have an unmatched jSon string, if you want to convert into a list, try this
{
"id": "MyID",
"values": [
{
"id": "100",
"diaplayName": "MyValue1",
},
{
"id": "200",
"diaplayName": "MyValue2",
}
]
}
This is possible too:
using System.Web.Helpers;
var listOfObjectsResult = Json.Decode<List<DataType>>(JsonData);
This takes the JsonElement and deserializes it to List of objects.
List<object> draftInvoices = JsonConvert.DeserializeObject<List<object>>(jsonDrafts.ToString());
Example:
[HttpPost]
[Route("CreateDraft")]
public async Task<IActionResult> CreateDraft([FromBody] JsonElement jsonDrafts)
{
List<object> draftInvoices = JsonConvert.DeserializeObject<List<object>>(jsonDrafts.ToString());
for (int i = 0; i < draftInvoices.Count; i++)
{
........
}
You may use Json.Net framework to do this.
Just like this :
Account account = JsonConvert.DeserializeObject<Account>(json);
the home page : http://json.codeplex.com/
the document about this : http://james.newtonking.com/json/help/index.html#