How to pass class name to JSON DeserializeObject at runtime? - c#

Given that I have JSON like this:
[
{
"ct_IncludeinSummary": true,
"ct_allocationid": "12345",
"allocationclassname": "group1",
"allocationname": "name1",
"opendate": "2018-12-30T05:00:00",
"closeddate": null,
"yearendvalue": 2863.93,
"qrgendvalue": 2.06,
"ct_risk": 2
},
{
"ct_IncludeinSummary": true,
"ct_allocationassetid": "5678",
"allocationclassname": "group2",
"allocationname": "name2",
"opendate": "2018-12-30T05:00:00",
"closeddate": null,
"yearendvalue": 13538223.76,
"qrgendvalue": 17337143.84,
"ct_risk": 3
},
{
"ct_IncludeinSummary": true,
"ct_allocationassetid": "89012",
"allocationclassname": "group3",
"allocationname": "name3",
"opendate": "2019-11-18T05:00:00",
"closeddate": null,
"yearendvalue": 0.0,
"qrgendvalue": 561480.62,
"ct_risk": 5
}
]
I can deserialize the results into a defined model and it works just fine.
var summaryConciseData = JsonConvert.DeserializeObject<List<SummaryConciseData>>(jsonresult);
public class Summaryconcisedata
{
public Summaryconcisedata(
bool ct_IncludeinSummary,
string ct_allocationassetid,
string allocationclassname,
string allocationname,
DateTime opendate,
DateTime? closeddate,
double? yearendvalue,
double? qrgendvalue,
int ct_risk
)
{
this.IncludeinSummary = ct_IncludeinSummary;
this.allocationid = ct_allocationassetid;
this.allocationclassname = allocationclassname;
this.allocationname = allocationname;
this.opendate = opendate;
this.closeddate = closeddate;
this.yearendvalue = yearendvalue;
this.qrgendvalue = qrgendvalue;
this.risk = risk;
}
public bool IncludeinSummary { get; }
public string allocationid { get; }
public string allocationclassname { get; }
public string allocationname { get; }
public DateTime opendate { get; }
public DateTime? closeddate { get; }
public double? yearendvalue { get; }
public double? qrgendvalue { get; }
public int risk { get; }
}
What I am trying to do is to have a large number of classes (Around 30 in all) I can deserialize and load into models
var summaryConciseData = JsonConvert.DeserializeObject(jsonresult, Type.GetType("API.HelperClass.SummaryConciseData"));
I get the following error:
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'API.HelperClass.SummaryConciseData' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
Any idea on how I this can be a List<> ?
I've gone through most all of the similar questions to be found but none refer to any data that is in a List

MakeGenericType on list/ienumerable type should work just fine:
var listType = typeof(List<>).MakeGenericType(Type.GetType("API.HelperClass.SummaryConciseData");
var summaryConciseData = JsonConvert.DeserializeObject(jsonresult, listType);

Related

How to extract those values from the JSON string

I have this JSON string but are not sure how I will parse out the values that are inside:
has
has2
I do succeed to parse out the "id" correctly but are not sure how to access:
CORS
CORS2
CORS3
CORS4
I get the error:
'Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.String[]' because the type requires a JSON array (e.g. [1,2,3])
I have pasted the JSON in the pastebin:
https://pastebin.com/iWgGV9VK
The code I have:
public void getInfo()
{
String JSONstring = "{ id: 'hello', name: 'Hello',has:{ CORS: false,CORS2: true},has2:{ CORS3: false,CORS4: true}}";
String id = ""; List<String> has = new List<String>(); List<String> has2 = new List<String>();
var deserializedTicker = JsonConvert.DeserializeObject<JsonInfo>(JSONstring);
id = deserializedTicker.id;
has = deserializedTicker.has.ToList();
has2 = deserializedTicker.has.ToList();
}
public class JsonInfo
{
public String id { get; set; }
public String[] has { get; set; }
public String[] has2 { get; set; }
}
I am trying with the dynamic approach using an object but gets an error here also:
''Newtonsoft.Json.Linq.JValue' does not contain a definition for 'id''
//responseBody holds the JSON string
dynamic stuff = JsonConvert.DeserializeObject(responseBody);
foreach (var info in stuff)
{
dynamic id = info.Value.id; //''Newtonsoft.Json.Linq.JValue' does not contain a definition for 'id''
dynamic has = info.Value.has;
dynamic has2 = info.Value.has2;
if (has != null && has2 != null)
{
dynamic cors = has.CORS;
if(cors != null)
{
MessageBox.Show(cors.ToString());
}
}
}
First off, let's correct your JSON:
{
"id": "hello",
"name": "Hello",
"has": {
"CORS": false,
"CORS2": true
},
"has2": {
"CORS3": false,
"CORS4": true
}
}
Now, the problem you are experiencing is because you are attempting to deserialize the value in "has" and "has2" as arrays. In the JSON, they are not arrays; they are objects. As such, you need to define new classes with the same properties so the JSON can be properly deserialized:
public class JsonInfo
{
public string id { get; set; }
public string name { get; set; }
public JsonHasInfo has { get; set; }
public JsonHas2Info has2 { get; set; }
}
public class JsonHasInfo
{
public bool CORS { get; set; }
public bool CORS2 { get; set; }
}
public class JsonHas2Info
{
public bool CORS3 { get; set; }
public bool CORS4 { get; set; }
}
Now you should be able to deserialize the (correct) JSON properly:
String JSONstring = "{ \"id\": \"hello\", \"name\": \"Hello\", \"has\": { \"CORS\": false, \"CORS2\": true }, \"has2\": { \"CORS3\": false, \"CORS4\": true } }\";"
var deserializedTicker = JsonConvert.DeserializeObject<JsonInfo>(JSONstring);
You json was incorrect, the key has contains a dict no list.
You need change your deserialize to dictionary or change your json.
Here you can see an example:
https://json-schema.org/understanding-json-schema/reference/array.html#array
In your JSON, has is an object, not an array. You should model your class to support an object containing the attributes CORS, CORS2, and so on, and so forth.
Edit: If you want to stick to has being an array, you should change your JSON to match what an array expects, which could be like: has: [ false, true ], and omit the CORS thing.

Error while de-serializing json array [duplicate]

This question already has answers here:
Serialize and Deserialize Json and Json Array in Unity
(9 answers)
Closed 4 years ago.
I'm trying to deserialize a Json string.
This is my code:
[System.Serializable]
public class SharedWorlds
{
public int worldId { get; set; }
public System.DateTime uploaded { get; set; }
public string username { get; set; }
public string levelName { get; set; }
public string gameVersion { get; set; }
public string description { get; set; }
public string filename { get; set; }
public string screenshot1 { get; set; }
public string screenshot2 { get; set; }
public string userTag { get; set; }
public string userURL { get; set; }
public double price { get; set; }
public int nrDownload { get; set; }
public int votes { get; set; }
}
[System.Serializable]
public class Record {
public List<SharedWorlds> record;
}
try {
SDE3D _webService = new SDE3D();
result= _webService.GetMassiveWorldsList ();
var records = JsonUtility.FromJson<Record>(result);
}
catch(System.Exception ex) {
Debug.Log (ex.Message.ToString ());
}
And this is my valid jSon (here two records, but I want to send many records per time).
[
{
"worldId": 5,
"uploaded": "/Date(1524875719000)/",
"username": "quik",
"levelName": "Station",
"gameVersion": "1.0.1",
"description": "iwoeijksf",
"filename": "0000003.dat",
"screenshot1": "0000003a.png",
"screenshot2": "0000003b.png",
"userTag": "",
"userURL": "",
"price": 0,
"nrDownload": 5,
"votes": 5
},
{
"worldId": 4,
"uploaded": "/Date(1524875659000)/",
"username": "aksio",
"levelName": "Garage",
"gameVersion": "1.0.1",
"description": "Adlkld",
"filename": "0000003.dat",
"screenshot1": "0000003a.png",
"screenshot2": "0000003b.png",
"userTag": "",
"userURL": "",
"price": 0,
"nrDownload": 4,
"votes": 4
}
]
I'm getting error:
"ArgumentException: JSON must represent an object type."
I'm pretty sure the error is in this code line:
var records = JsonUtility.FromJson<Record>(result);
How to deserialize an array of json object ?
Thanks
Because your JSON data is not a Record. It's a collection of SharedWorlds. So something like this:
var sharedWorlds = JsonUtility.FromJson<SharedWorld[]>(result);
Or perhaps:
var sharedWorlds = JsonUtility.FromJson<List<SharedWorld>>(result);
From which you could create a Record:
var record = new Record { record = sharedWorlds };
If the JSON needs to deserialize into a Record then it would need to be in the format of a Record object:
{
"record":
[
/* the rest of your JSON within the square brackets */
]
}
Then it would be a Record:
var record = JsonUtility.FromJson<Record>(result);
*Side note: Your class and variable names and the pluralizations you're using are really confusing. The semantics of which is probably not making your debugging any easier for you.
You get to script collection of object no one single object in your JSON

deserialize inconsistent json to object c#

Can someone tell me how to deserialize JSON to a C# (without using C# dynamic) object when JSON string is having dynamic array of data?
Given below JSON is having Boxes object and it can contain Array of fashion items (It can be pants, sweater, shoes,...etc)
{
"task": {
"id": 269740275,
"status": "success",
"error": null,
"date_created": "2017-02-16T10:33:41.827688Z",
"date_updated": "2017-02-16T10:33:42.417778Z",
"data": {
"width": 1062,
"boxes": {
"top-shirt": [
{
"xmin": 0.249980241060257,
"ymin": 0.1535395532846451,
"ymax": 0.476559966802597,
"xmax": 0.6146213412284851,
"proba": 0.9977585077285767
}
],
"shoe": [
{
"xmin": 0.3686676025390625,
"ymin": 0.9223044514656067,
"ymax": 0.9838011264801025,
"xmax": 0.4768480360507965,
"proba": 0.9748706817626953
}
],
"pants": [
{
"xmin": 0.3451904654502869,
"ymin": 0.4616038501262665,
"ymax": 0.909162700176239,
"xmax": 0.6047541499137878,
"proba": 0.9983627200126648
}
]
},
"height": 1503
}
}
}
You can use a dictionary to handle the dynamic part of the JSON (boxes).
Define your classes like this:
public class RootObject
{
public Task task { get; set; }
}
public class Task
{
public int id { get; set; }
public string status { get; set; }
public object error { get; set; }
public DateTime date_created { get; set; }
public DateTime date_updated { get; set; }
public Data data { get; set; }
}
public class Data
{
public int width { get; set; }
public Dictionary<string, List<Item>> boxes { get; set; }
public int height { get; set; }
}
public class Item
{
public double xmin { get; set; }
public double ymin { get; set; }
public double ymax { get; set; }
public double xmax { get; set; }
public double proba { get; set; }
}
Then deserialize like this:
RootObject obj = JsonConvert.DeserializeObject<RootObject>(json);
Fiddle: https://dotnetfiddle.net/Sxz8P3
Use NuGet to fetch the Newtonsoft.JSON package.
Then you can use linq-to-json to handle this kind of data object.
For example, assuming your example JSON string is stored in input,
var message = JObject.Parse(input);
var width = (int)message["task"]["data"]["width"];
var height = (int)message["task"]["data"]["height"];
Console.WriteLine(width + " " + height);
var boxes = message["task"]["data"]["boxes"];
foreach (var box in boxes.Children<JProperty>())
{
Console.WriteLine(box.Name) ;
}
This is pretty close to Javascript and works well.
I think O. Jones provided the easiest solution, using Newtonsoft, Newtonsoft is literally the best possible way to do anything with JSON in C# and without any headaches.
Here's one of the simplest examples
string json_string = #"{
Firstname: ""Jane"",
Lastname: ""Doe"",
Age: 36,
IsEmployed: true,
IsMarried: true,
Children: 4
}";
var person = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(json_string);
Console.WriteLine(person.Forename);
Console.WriteLine(person.Lastname);
Console.WriteLine(person.Age);
Console.WriteLine(person.IsEmployed);
Console.WriteLine(person.IsMarried);
Console.WriteLine(person.Children);
It generates objects on the fly, no matter the structure!
I wrote a simple, easy-to-follow article here https://turmanauli.medium.com/a-complete-guide-for-serializing-json-to-dynamic-objects-on-the-fly-in-c-7ab4799f648d
about how to use Newtonsoft in your Visual Studio project.

Can't deserialize json

Can someone help me figure out how to deserialize this using json.net in C#? I have already successfully parsed a different json but its format was different. I've tried to use object and it says it needs to be an array and then I change it to array it says it needs to be an array..
Oh and there can be additional arrays with different "TYPE"..
"[
{
"ID": 1,
"TYPE": 1,
"APP_TAG": 1,
"alert": "[13:13] This is a Test Message - 0.",
"sound": "Default",
"badge": 0
}
]"
Since it is an array/list
public class Item
{
public int ID { get; set; }
public int TYPE { get; set; }
public int APP_TAG { get; set; }
public string alert { get; set; }
public string sound { get; set; }
public int badge { get; set; }
}
var items = JsonConvert.DeserializeObject<List<Item>>(json);
string json = #"[
{
'ID': 1,
'TYPE': 1,
'APP_TAG': 1,
'alert': '[13:13] This is a Test Message - 0.',
'sound': 'Default',
'badge': 0
}
]";
var items = Newtonsoft.Json.JsonConvert.DeserializeObject(json);

Deserializing array of enum values wih JSON.NET

I'm trying to use JSON.NET to deserialize a response from a third-party web service. This is the full code of my (contrived) example showing what I'm trying to do:
namespace JsonNetTests
{
public enum Parameter
{
Alpha = 1,
Bravo = 2,
Charlie = 3,
Delta = 4
}
public class ResponseElement
{
public int Id { get; set; }
public string Name { get; set; }
[JsonProperty(ItemConverterType = typeof(StringEnumConverter))]
public Parameter[] Parameters { get; set; }
}
public class ResponseBody
{
public string Locale { get; set; }
public string[] Errors { get; set; }
public ResponseElement[] ResponseElements { get; set; }
}
[TestFixture]
public class JsonNetTest
{
[Test]
public void TestEnumArray()
{
string jsonResponse = #"
{""ResponseBody"": {
""Locale"": ""en-US"",
""Errors"": [],
""ResponseElements"": [{
""Id"": 1,
""Name"": ""ABC"",
""Parameters"" : {
""Parameter"" : ""Alpha""
},
}, {
""Id"": 2,
""Name"": ""BCD"",
""Parameters"" : {
""Parameter"" : ""Bravo""
},
}
]
}}
";
JObject rootObject = JObject.Parse(jsonResponse);
JToken rootToken = rootObject.SelectToken("ResponseBody");
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.MissingMemberHandling = MissingMemberHandling.Error;
ResponseBody body = JsonConvert.DeserializeObject<ResponseBody>(rootToken.ToString(), settings);
foreach (var element in body.ResponseElements)
{
Console.WriteLine(string.Format("{0}: {1}", element.Id, element.Name));
foreach (var parameter in element.Parameters)
{
Console.WriteLine(string.Format("\t{0}", parameter));
}
}
}
}
}
I get the following exception:
Newtonsoft.Json.JsonSerializationException : Cannot deserialize JSON object (i.e. {"name":"value"}) into type 'JsonNetTests.Parameter[]'.
The deserialized type should be a normal .NET type (i.e. not a primitive type like integer, not a collection type like an array or List) or a dictionary type (i.e. Dictionary).
To force JSON objects to deserialize add the JsonObjectAttribute to the type. Path 'ResponseElements[0].Parameters.Parameter', line 9, position 21.
I tried to use the ItemConverterType attribute to specify how the array should be deserialised:
[JsonProperty(ItemConverterType = typeof(StringEnumConverter))]
But this does not help either. Can someone advise?
You're trying to stuff an object into an array. ResponseElement.Parameters is an array of enums where you're json code is using an object to describe each parameter.
Your json looks like this:
// some json
"Parameters" : {
"Parameter" : "Alpha"
},
// more json
But to translate it into an array of enums it should look like this:
// some json
"Parameters" : [ "Alpha", "Bravo" ],
// more json
If you can't change the json, you can change your model as so:
public enum ParameterEnum
{
Alpha = 1,
Bravo = 2
}
public ParameterContainer
{
[JsonProperty(ItemConverterType = typeof(StringEnumConverter))]
public ParameterEnum Parameter {get;set;}
}
public class ResponseElement
{
public int Id { get; set; }
public string Name { get; set; }
public ParameterContainer[] Parameters { get; set; }
}
Effectively, you'll serialize the json into an array of ParameterContainers which will expose their values.

Categories

Resources