I've searched far and beyond but cannot find a good solution for this problem.
I have a data set that looks like this(Only strings and null-values):
"rows": [
[
"string1",
"string2",
null,
"string4"
],
[
"string1",
null,
"string3",
null
],etc...
I'm getting this data from an api using RestSharp and want to shuffle it in to my database but I'm stuck at how to convert the data to POCOS where an array nested in 'rows' resembles an object, a flat one at that with only string properties.
I have no code as of this moment since nothing is even close to working...
Any fancy suggestions on how to accomplish this?
Cheers!
Probably the best and safest way is to write it manualy. If you are using vs2015 you can also copy the json and paste it as class.
You can find this option here:
Another option is to use a website like http://json2csharp.com/ here you can paste the JSON and this will also generate classes for your JSON. Keep in mind that these generator are not 100% accurate so you might have to change some properties your self.
for you example this would look something like this:
public class MyClass
{
public List<string> rows { get; set; }
}
or with cells
public class RootObject
{
public List<List<string>> rows { get; set; }
}
Ones we got the model we can use a lib like JSON.net to deserialize our JSON into our model. On the website is also some extra documentation on how to use JSON.net
var model = JsonConvert.DeserializeObject<MyClass>(json); //json being the json string.
Test:
var c = new MyClass()
{
rows = new List<string>()
{
"string1",
"string2",
"string3"
}
};
Console.WriteLine(JsonConvert.SerializeObject(c));
Console.Read();
Result:
{
"rows": [
"string1",
"string2",
"string3"
]
}
With cell list
Test:
static void Main(string[] args)
{
var c = new MyClass()
{
rows = new List<List<string>>()
{
new List<string>() {"string1","string2","string3" }
}
};
Console.WriteLine(JsonConvert.SerializeObject(c));
Console.Read();
}
public class MyClass
{
public List<List<string>> rows { get; set; }
}
Result:
{
"rows": [
[
"string1",
"string2",
"string3"
]
]
}
You should at least have the input you're receiving from that API, right?
If it's a string, you can use Newtonsoft to deserialize that JSON into an object:
var obj = JsonConvert.DeserializeObject(jsonInput)
If you know that the input is always going to be of the same type, you can map that to a class like the following, to benefit from the strongly type advantages.
public class Poco
{
public string[] Cell { get; set; }
}
As you are using RestSharp you should just need to create a class and pass that to the deserializer as its target, e.g.:
public class Poco
{
public List<List<string>> rows { get; set; }
}
Which can then be used as so:
var result = client.Execute<Poco>(request);
Related
I've got a JSON representation of an object along with the relevant model classes listed below. The two classes MinionSettings and LeeSettings are derived classes from a base abstract generic class.
{
"charSetting": {
"minionSettings": {
"key": "minionSettings",
"value": [1,2,3]
},
"leeSettings": {
"key": "leeSettings",
"value": [
{
"baseAD": 1,
"baseAP": 1,
"visible": true
}
]
}
}
}
public class CharacterSettingsWrapper
{
public CharacterSettings CharSetting { get; set; }
}
public class CharacterSettings
{
public MinionSettings MinionSettings { get; set; }
public LeeSettings LeeSettings { get; set; }
}
[DataContract]
public class MinionSettings : CharacterSetting<List<int>>
{
public MinionSettings()
{
Key = "minionSettings";
Value = new List<int>();
}
}
public class LeeSettings : CharacterSetting<List<LeeSetting>>
{
public LeeSettings()
{
Key = "leeSettings";
Value = new List<LeeSetting>();
}
}
Is there any way to keep all the fields in the CharacterSettings class but have them removed from the JSON representation of the object while keeping the relevant key/value pair, so I'd like the JSON to look like below. If not, is there anything else that I could do to achieve this?
I've tried using my base abstract class but since its abstract, I can't make an instance of it so it doesn't quite work, and this data is being extracted from a JSON and then put into a relevant object which based on the derived classes (like the two classes MinionSettings and LeeSettings)
{
"charSetting":[
{
"key":"minionSettings",
"value":[
1,
12,
3
]
},
{
"key":"leeSettings",
"value":[
{
"baseAD":1,
"baseAP":1,
"visible":true
}
]
}
]
}
You can solve this problem purely by using JObject and JArray objects without the need to create and use any domain objects.
In the bellow code I've assumed that the nodes exist (to keep the code simple) but in production code please prefer TryGetValue (Ref) over the index operator (Ref).
//Retrieve the nodes from the original json
var json = File.ReadAllText("sample.json");
var root = JObject.Parse(json);
var charSetting = root["charSetting"];
var minionSettings = charSetting["minionSettings"];
var leeSettings = charSetting["leeSettings"];
//Construct the new json based on the retrieved values
var newcharSetting = new JArray();
newcharSetting.Add(minionSettings);
newcharSetting.Add(leeSettings);
var newRoot = new JObject();
newRoot.Add("charSetting", newcharSetting);
Console.WriteLine(newRoot.ToString());
I also have to mention that this code heavily relies on the sample json's structure. So, it is not generic enough to handle any kind of structure which resembles to this.
The printed output would look like this:
{
"charSetting": [
{
"key": "minionSettings",
"value": [
1,
2,
3
]
},
{
"key": "leeSettings",
"value": [
{
"baseAD": 1,
"baseAP": 1,
"visible": true
}
]
}
]
}
I've been trying to deserialize the following JSON string into a model using Newtonsoft's Json library, but failing to do so. The json string is as follows:-
[
[
{
"events": [
{
"d": "Dec 2019 Final",
"e": "Released 5 Mar 2020"
}
]
}
],
[
{
"events": [
{
"d": "Some String",
"e": "Some Other string"
}
]
}
]
]
I tried doing so by creating its model using Visual Studio internal tool for json to C# (paste special). Also tried creating the models using QuickTypes.io, but so far nothing worked.
The best I can do is parse the api response as List<List<object>> and then manually get the values by iterating its keys & values, which is something I totally want to avoid.
Is there a better way to handle this data?
I hope I understand your question correctly.If you want to stick to Anonymous types, you could make use of JsonConvert.DeserializeAnonymousType for the purpose.
var innerAnonymousType = new {d=string.Empty,e=string.Empty};
var innerAnnonymousTypeList = CreateList(innerAnonymousType);
var outerAnonymousType = CreateList(new {events = innerAnnonymousTypeList});
var result = JsonConvert.DeserializeAnonymousType(json, CreateList(outerAnonymousType));
Where CreateList is defined as
public static List<T> CreateList<T>(params T[] elements)
{
return new List<T>(elements);
}
Using JsonConvert.DeserializeAnonymousType
Output Sample
You can use a base model and parse your json:
public class BaseClass
{
public List<EventModel> Events { get; set; }
}
public class EventModel
{
[JsonProperty(PropertyName = "d")]
public string Date { get; set; }
[JsonProperty(PropertyName = "e")]
public string Event { get; set; }
}
And for deserialize json to model use this:
var model = JsonConvert.DeserializeObject<List<List<BaseClass>>>("your json");
I am very new to JSON, so I may have missed something. But here's what I am attempting.
I want to Deserialize the following type of JSON
{
"Size":
{
"Creature":
{
"Dragon":
[
"Huge",
"Colossal",
"Mountain-sized"
],
"Wolf":
[
"Pup",
"Fully grown",
"Giant"
]
},
"Building":
[
"Small",
"Medium",
"Large"
]
}
}
The core function of the JSON is intended so that I am not sure how nested it may become over time. With creature having subtypes depending on what kind of creature it is, and same for building and so on.
I've attempted with this code
using StreamReader r = new StreamReader("Storage.json");
string json = r.ReadToEnd();
CoreStorageDict = JsonConvert.DeserializeObject<Dictionary<string, List<string>>>(json);
I would like to Deserialize it into a dictionary as directly as possible, but I've yet to find a good way to do it and I think I am missing something fundamental about the whole system.
Is the JSON wrong or is my code wrong? Or both perhaps?
If you define the following classes:
public class Creature
{
public IList<string> Dragon { get; set; }
public IList<string> Wolf { get; set; }
}
public class Size
{
public Creature Creature { get; set; }
public IList<string> Building { get; set; }
}
public class Example
{
public Size Size { get; set; }
}
and then try to deserialize your json you will make it. You can alter the name of classes as you want. For the names above you have just to do this:
var result = JsonConvert.DeserializeObject<Example>(json);
What is the problem with the approach you followed ?
The problem is that you have nested types. So you have to declare each and any type properly in order the deserialization work.
How you can find which classes are needed to be declared ?
There are may tools out there that do this job. The one I used is the following one JSON Utils. Provided that you have a valid json, these tools can auto generate the required classes. If I am correct, also Visual Studio, provides you with such a functionality.
Making classes is definitely a good way to do it and I agree with Christos.
However if you're doing a one-time thing and don't want to bother making classes you can hack it by deserializing the whole thing to dynamic and then re-serializing and deserializing the part you need, to your expected type, like this.
var json = #"{
""Size"": {
""Creature"": {
""Dragon"": [
""Huge"",
""Colossal"",
""Mountain-sized""
],
""Wolf"": [
""Pup"",
""Fully grown"",
""Giant""
]
},
""Building"": [
""Small"",
""Medium"",
""Large""
]
}
}";
var deserialized = JsonConvert.DeserializeObject<dynamic>(json);
var thePartYouWant = deserialized.Size.Creature;
var dict = (Dictionary<string, List<string>>) JsonConvert
.DeserializeObject<Dictionary<string, List<string>>>(
(JsonConvert.SerializeObject(thePartYouWant)));
dict.Keys.ToList().ForEach(Console.WriteLine);
I have the following json that contains an unnamed array and other named properties. I'd like to know how to deserialize it to a class, using Newtonsoft.Json.
{
"message": "success",
[
{
"timestamp": 1509723862,
"tid": 84823616,
"price": "7344.7",
"amount": "0.36108123",
"exchange": "bitfinex",
"type": "sell"
},
{
...
}
]
}
I know I could deserialize the array using
serializer.DeserializeObject< List < Response > >(serializedObject), but as the json contains other properties, it is not a json-array string.
Is there any configuration that I could use to tell Newtonsoft.Json to deserialize the array into a List, and the 'message' property to a string, in the class bellow:
public class Response
{
public string Message {get;set;}
public List<ResponseItem> ResponseItems {get;set;}
}
public class ResponseItem {
string timestamp {get;set;}
(...)
}
A JSON can't have both an unnamed array and a named value on the same level. The JSON is invalid. Either everything is keyed, or it's an unkeyed array. Can't have both.
I think it's not a good idea to concate the two Json's.
Use your own Deserializer and pass your two Json's:
public static class ResponseDeserializer
{
public static Response Deserialize(string psMessage, string psResponeItems)
{
dynamic loMessage = JsonConvert.DeserializeObject(psMessage);
return new Response()
{
Message = loMessage.message,
ResponseItems = JsonConvert.DeserializeObject<List<ResponseItem>>(psResponeItems)
};
}
}
And use it:
string lsMessage = "{\"message\":\"Unknown symbol\"}";
string lsResponseItems = "[{\"timestamp\":1509726632,\"tid\":84840931,\"price\":\"7298.8\",\"amount\":\"0.0044733\",\"exchange\":\"bitfinex\",\"type\":\"sell\"},{\"timestamp\":1509726630,\"tid\":84840921,\"price\":\"7297.3\",\"amount\":\"0.11550649\",\"exchange\":\"bitfinex\",\"type\":\"sell\"},{\"timestamp\":1509726630,\"tid\":84840911,\"price\":\"7297.2\",\"amount\":\"0.0214149\",\"exchange\":\"bitfinex\",\"type\":\"buy\"},{\"timestamp\":1509726629,\"tid\":84840909,\"price\":\"7297.2\",\"amount\":\"0.41004892\",\"exchange\":\"bitfinex\",\"type\":\"buy\"}]";
var loResponse = ResponseDeserializer.Deserialize(lsMessage, lsResponseItems);
Console.WriteLine(loResponse.Message);
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