I am using C# .NET 4.0 to parse a JSON into a custom object. I am using JavaScriptSerializer.Deserialize to map it to a class that I wrote. Problem is, the JSON's name/value pairs are not static and vary depending on the argument isChain, as seen in this JSON fragment (better link at bottom):
{
"STATE_WALK_LEFT":{
"isChain":"1",
"x":"1"
},
"STATE_WALK_LEFT_0":{
"x":"0"
},
"STATE_WALK_LEFT_1":{
"x":"40"
},
"STATE_WALK_LEFT_2":{
"x":"80"
},
"STATE_WALK_RIGHT":{
"isChain":"0"
},
"STATE_RUN_LEFT":{
"isChain":"0"
}
}
The chains can have anywhere from _STATE_0 to _STATE_25 entries in the chains. Is there some way to store this data so I don't have to write 12*26 empty classes like so:
public StateWalkLeft0 STATE_WALK_LEFT { get; set; }
public StateWalkLeft0 STATE_WALK_LEFT_0 { get; set; }
public StateWalkLeft1 STATE_WALK_LEFT_1 { get; set; }
public StateWalkLeft2 STATE_WALK_LEFT_2 { get; set; }
public StateWalkLeft3 STATE_WALK_LEFT_3 { get; set; }
Is there a library or some other way I could use to partially parse only the STATE_0, STATE_1, etc fields? Could you maybe suggest a way to add these recently added JSON pairs?
Edited to clarify:
To get an idea of what I'm working with, here is the Class derived from the JSONs:
Check out my full Class to get an idea of what the JSONs contain
Basically, I just need a way to store these recently implemented chains in this class somehow for processing. All of those classes/properties are generated from these JSONs.
Use Newtonsoft Json.NET and as example following code
internal struct ChainX
{
public int x { get; set; }
public int isChain { get; set; }
}
static string json =
#"{
""STATE_WALK_LEFT"":{
""isChain"":""1"",
""x"":""1""
},
""STATE_WALK_LEFT_0"":{
""x"":""0""
},
""STATE_WALK_LEFT_1"":{
""x"":""40""
},
""STATE_WALK_LEFT_2"":{
""x"":""80""
},
""STATE_WALK_RIGHT"":{
""isChain"":""0""
},
""STATE_RUN_LEFT"":{
""isChain"":""0""
}
}";
and a line of code to deserialize to Dictionary:
var values = JsonConvert.DeserializeObject<Dictionary<string, ChainX>>(json);
after that you can simple access values by dictionary key:
ChainX valueWalkLeft1 = values["STATE_WALK_LEFT_1"];
Related
I am attempting to use JsonSerializer.Deserialize() from System.Text.JSON in .NET 6.
I have no control over the format of the JSON.
I have used it successfully in the past but now the data I need to consume is more complicated (but not VERY complicated). I am assuming that I am simply describing my data incorrectly.
I have tried several things.... but the description below is the only way so far that I could consume the data at all.
I think my biggest problem is that I am trying to use the wiz-bang "Paste Special -> Paste JSON as Classes" without really understanding how to form my classes for serialization/deserialization.
Here is a simple example of the JSON I am trying to consume:
[
{
"version": "1.0b",
"sub_version": "x.y.barf"
},
{
"somestring": "I am a string",
"isCool": false,
"a_cool_array": [
"bob",
"jill",
"pete"
]
}
]
If I use the whiz-bang "Paste Special" tool, I get the following generated for me.
public class Rootobject
{
public Class1[] Property1 { get; set; }
}
public class Class1
{
public string version { get; set; }//<-- I need these to remain in their own object
public string sub_version { get; set; }//<-- I need these to remain in their own object
public string somestring { get; set; }
public bool isCool { get; set; }
public string[] a_cool_array { get; set; }
}
Here is the problem that I have.
The whiz-bang tool put my first object (with one version strings) and second (more complicated) object into the same object.
If I use a call like this:
var deserializedJSON = JsonSerializer.Deserialize<List<Class1>>(myJSONTextHere);
I end up with two objects in the list.
The first one has the versions filled out, the second one only has the other fields filled out.
This all makes sense to me but I don't know how to get around the problem.
I need these objects to model the JSON and I need them to save back in the same format when I re-serailize the modified classes elsewhere. This isn't my exact problem as I have simplified it for the question.
I have found one way around this problem.
It is ugly but seems to work. I hate that my code has to know about the data it is manipulating.
I used the actual JSON DOM to split the two disparate classes into individual JSON objects, then used the class de-serializer to load the individual objects into their given types.
In the following example, I am not checking anything.. I happen to know the order of the objects. I could check the raw JSON to make sure it was what I was looking for. In this case, I don't need to.
So, instead of taking the class structure as pasted by the super spiffy "Paste Classes from JSON" thingamajigger.. I split the classes myself.
Like this:
public class VersionClass
{
public string version { get; set; }
public string sub_version { get; set; }
}
public class DataClass
{
public string somestring { get; set; }
public bool isCool { get; set; }
public string[] a_cool_array { get; set; }
}
Then, I can load the JSON into the objects I need like this:
using var jsonDoc = JsonDocument.Parse(jsonText);
var versionClass = jsonDoc.RootElement[0].Deserialize<VersionClass>();
var dataClass = jsonDoc.RootElement[1].Deserialize<DataClass>();
I hope this helps someone having the same problem.
Your json needs to look like this:
{
"class1": [
//more json
],
"class2": [
//more json
]
}
Then you will have:
public class RootObject
{
// class1 and 2 in here
}
public class Class1
{
}
public class Class2
{
}
I'm trying to de-serialize a large JSON file using JSON.net. I've been unable to de-serialize the nested dictionaries inside this file. The name of the object containing these dictionaries repeats thousands of times inside the file. The code I provided is a small, shortened version of the file I'm dealing with to show an example of these repeating nested dictionaries. I'm looking for a solution to de-serializing the contents of thousands of "image_uris" into classes I suppose, such that I can access the "small", "medium", and "large" keys and values from each "image_uris" object.
[
{
"object":"card",
"id":"789",
"image_uris":
{
"small":"https://img...98713",
"medium":"https://img...89712",
"large":"https://img...97123",
}
},
{
"object":"card",
"id":"654",
"image_uris":
{
"small":"https://img...43243",
"medium":"https://img...26267",
"large":"https://img...00812",
}
},
{
"object":"card",
"id":"091",
"image_uris":
{
"small":"https://img...98760",
"medium":"https://img...92331",
"large":"https://img...87690",
}
}
]
I've been working in the Unity Game Engine, with C#, with JSON.net. I have tried using http://json2csharp.com/ by feeding it the entire JSON file. It spits out ~1700 lines of code with implementation instructions commented at the top. I'm not sure how to access all the generated classes and data in those classes by following those instructions. Those instructions are as follows:
// <auto-generated />
//
// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
//
// using QuickType;
//
// var scryfallDefaultCards = ScryfallDefaultCards.FromJson(jsonString);
Not sure what the problem is but I just copy pasted your JSON snippet into the same site you went to and got this:
public class ImageUris
{
public string small { get; set; }
public string medium { get; set; }
public string large { get; set; }
}
public class RootObject
{
public string #object { get; set; }
public string id { get; set; }
public ImageUris image_uris { get; set; }
}
But your JSON is an array and you should just deserialize like this:
var result = JsonConvert.DeserializeObject<List<RootObject>>(jsonString);
It should work the same using your larger JSON string
This is the JSON object I am receiving from a GET request:
{
"data": {
"valve_maker": [],
"water_volume": [
"15L",
"20L",
"..."
],
"cylinder_manufacturer": [
"Tianhai"
],
"qc_stamp": [
"TS"
],
"reference_standard": [
"GB 5099"
],
"production_licence": [
"TS2210752-2016"
],
"valve_production_licence": [
"TSF210030"
],
"rate_of_residual_deformation": {
"1": "<3%",
"2": "<10%"
},
"material_number": {
"1": "30CrMo",
"2": "34CrMo4",
"3": "..."
},
"heat_treatment": {
"1": "...",
"2": "..."
},
"drawing_number": {
"1": "...",
"2": "..."
},
"cylinder_thickness": []
}
right now, I am able to parse JSON objects with a simpler structure like :
{
"data": [
{
"gas_id": "ID of the gas",
"gas_name": "Gas name"
}
]
by using something like this:
private void jsonparsegas(string res)
{
JObject par = JObject.Parse(res);
foreach (JToken data in par["data"].Children())
{
string id = data["gas_id"].ToString();
string name = data["gas_name"].ToString();
if (this.cmbCylType.Items.Contains(name) == false)
{
this.cmbCylType.Items.Add(name);
}
}
}
When I try to apply the same thing to the more complicated JSON object, I get an error:
private void jsonparsecoc(string res)
{
//JObject par = JObject.Parse(res);
var jObj = (JObject)Newtonsoft.Json.JsonConvert.DeserializeObject(res);
foreach (var child in jObj["data"].Children())
{
string vMaker = child["valve_maker"].ToString(); //error thrown here right away
string wVolume = child["water_volume"].ToString();
string cMan = child["cylinder_manufacturer"].ToString();
string QC = child["qc_stamp"].ToString();
string rStandard = child["reference_standard"].ToString();
string pLicence = child["production_licence"].ToString();
string VPL = child["valve_production_licence"].ToString();
string rrd = child["rate_of_residual_deformation"].ToString();
string mNum = child["material_number"].ToString();
string hTreatment = child["heat_treatment"].ToString();
string dNum = child["drawing_number"].ToString();
string cThick = child["cylinder_thickness"].ToString();
}
Cannot access child value on Newtonsoft.Json.Linq.JProperty
I have tried a few different things I found on StackOverflow, but I don't really understand how Deserializing of the objects works. The simpler parsing works just fine, and allows me to add all "gas_name"s that I receive from my GET request to a combobox. The format the first "valve_maker" child of "data" seems to have the same structure as "gas_id" or "gas_name" in the more similar JSON object, but this is where I receive the error right away. If I had to guess at a cause for the error, I'd say it has something to do with the difference between using
"valve_maker": []
and using
"gas_id": "ID of the gas"
in the objects. also I notice "data" is followed by [] brackets in the simpler one, and {} in the more complicated one.
If anyone could link to some good reading material, or offer a good explanation of a solution/what's going on, I'd really appreciate it.
This part is the key to the problem you're having:
in the objects. also I notice "data" is followed by [] brackets in the simpler one, and {} in the more complicated one.
In JSON,
[] brackets enclose an array
{} brackets enclose an object
In both code examples, you are digging into the object by looping through the results using par["data"].Children(). To be consistent with the JSON model, JSON.NET defines different behavior for resolving children of objects and arrays. The children of an object are its properties and the children of an array are its items.
In your code, the input to jsonparsegas is an array of simple objects with 2 properties where the input to jsonparsecoc is a single complex objects with many properties.
In jsonparsegas, the Children() call gives you an array of all the simple gas objects. You loop through these objects and extract the values of "gas_id" and "gas_name" for each object. In your example data, there only happens to be one gas object so your code only executes once.
In jsonparsecoc, the Children() call actually gives you property values for the properties of the complex object, since the result is an object and not an array. So, when you loop through this result you can't access things like "valve_maker", because they are defined on the complex object and you have already stepped into the value for valve_maker then this executes.
The solution is simple. Don't loop through the properties in jsonparsecoc. Instead of foreach(var child in jObj["data"].Children()) you need something like var child = jObj["data"];. This will give you the reference to the object that actually contains each of the properties you are trying to access.
#smartcaveman did a good job of explaining what is going wrong with your code. However, you might find your data a little easier to process if you defined strongly-typed classes for it like this:
class RootObject
{
public Data Data { get; set; }
}
class Data
{
[JsonProperty("valve_maker")]
public List<string> ValveMaker { get; set; }
[JsonProperty("water_volume")]
public List<string> WaterVolume { get; set; }
[JsonProperty("cylinder_manufacturer")]
public List<string> CylinderManufacturer { get; set; }
[JsonProperty("qc_stamp")]
public List<string> QCStamp { get; set; }
[JsonProperty("reference_standard")]
public List<string> ReferenceStandard { get; set; }
[JsonProperty("production_licence")]
public List<string> ProductionLicense { get; set; }
[JsonProperty("valve_production_licence")]
public List<string> ValveProductionLicense { get; set; }
[JsonProperty("rate_of_residual_deformation")]
public Dictionary<string, string> RateOfResidualDeformation { get; set; }
[JsonProperty("material_number")]
public Dictionary<string, string> MaterialNumber { get; set; }
[JsonProperty("heat_treatment")]
public Dictionary<string, string> HeatTreatment { get; set; }
[JsonProperty("drawing_number")]
public Dictionary<string, string> DrawingNumber { get; set; }
[JsonProperty("cylinder_thickness")]
public List<string> CylinderThickness { get; set; }
}
You can deserialize the JSON to your classes like this:
RootObject obj = JsonConvert.DeserializeObject<RootObject>(json);
Demo here: https://dotnetfiddle.net/p0D7ze
public class Test{
public Data data{get;set;}
}
public class Data{
public List<string> Value_maker{get;set;}
public List<String> Water_Volume{get;set;}
public List<String> cylinder_manufacturer{get;set;}
}
Create Class structure Like that and after that use to deserialize
Jsonconvert.DeserializeObject(JsonString)
it will convert json into proper object, keep in mind structure should be proper and property name should be same as your json property
Hope It will Help you
I have to design a class based on a json template that i received. I'm stuck at this part of the json:
events: {
"door": [
5,
{
valueone: 27,
valuetwo: "something"
}
],
"window": [
2,
{
valueone: 13,
valuetwo: "something"
}
]
}
The best i can come up with is this property in the root object:
public Dictionary<string, EventData> Events { get; set; }
Where Events is defined like this:
public class EventData
{
public int valueone { get; set; }
public string valuetwo { get; set; }
}
This gives me for example the following output:
Events: {
door: {
valueone: 27,
valuetwo: "something"
}
}
But i have no idea how to design the class to get the numbers in the json example (5 and 2) in the output. I have tried to google for this for a long time today but i'm not quite sure what to search for.
Below is an outline of the code that would fit:
public class Event
{
public List<Elements> door { get; set; }
public List<Elements> window { get; set; }
}
public sealed class Elements
{
public int Id {get; set;}
public IDictionary<string, string> Values { get; set;}
}
You could build your objects with C# then use JSON.Net to serialise them to there JSON counterpart using:
Newtonsoft.Json.JsonConvert.SerializeObject(YOUR-OBJECT-HERE)
Depending on your needs you don't necessarily have to define types for capturing json like that:
For parsing you can use dynamic to capture the json as parsed by some json libararies.
For serializing json you can define anonymous objects like so
Json.Stringify(new {
events = new {
door = new[] {
5,
new { ... }
}
}
});
If you do need to define explicit types (because you want a model in your c# program) you may want to get more clarity about the domain that you are about to model. You can mirror the same JSON with different C# structures, so what really matters here is what the business/requirements do or will look like.
As #Habib noted in his comment you can use json2csharp.com to give you a hint (I did not know of that service until now - looks interesting!), but json2csharp.com will not be able to answer those questions.
Note: The "json" as it stands in your question is not valid JSON.
I'm working on a sandbox solution in Sharepoint, the important restrictions (regarding to this question) due to that are the use of .net 3.5 and there are no reflections allowed.
EXAMPLE 1
If I try to deserialize as JSON string into a simple class like this it works fine:
JSON STRING
{"field":"Picture1","url":"whatever"}
C# CLASS
public class PictureSetting
{
public string field { get; set; }
public string url { get; set; }
}
EXAMPLE 2
But if I try to deserialize a bit more complex string I get an error:
JSON STRING
{
"Rows": [
{
"Columns": [
{
"Width": "100"
}
]
}
]
}
C# CLASSES
internal class PageStructure
{
public List<StructureElement> Rows { get; set; }
public PageStructure()
{
Rows = new List<StructureElement>();
}
}
internal class StructureElement
{
public List<BlockAssigment> Columns { get; set; }
public StructureElement()
{
Columns = new List<BlockAssigment>();
}
}
internal class BlockAssigment
{
public string Width { get; set; }
}
ERROR
Request for the permission of type 'System.Security.Permissions.ReflectionPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.
*DESERIALIZATION
The code I use for deserialization of both examples is just standard .net:
var serializer = new JavaScriptSerializer();
var obj = serializer.Deserialize<PageStructure>("jsonstring");
So it seems that for the first example .net is not using reflection because that works. So the question is:
Is there a way to deserialize the second example without having .net using reflection internally?
Modifying both JSON string and C# classes are no problem, I just have to keep the structure (base object with rows including columns) somehow.
I suspect the biggest problem is actually here:
public class PictureSetting // public, works
versus
internal class PageStructure // non-public, permission denied
it sounds to me like the sandbox is preventing reflection of non-public types/members. This would be consistent with most sandboxes, for example Silverlight: you can use reflection, but only for things that the could would be able to do normally - i.e. access public types / members. Try making PageStructure, StructureElement and BlockAssigment into public classes.
You can use this service http://json2csharp.com/ to generate correct C# clasees for parsing json.