Complex json deserialization - c#

I have to deserialize the following json response (the Result list has variable length):
{
"ResultSet": {
"Query": "volkswagen",
"Result": [
{
"symbol": "VLKAY",
"name": "Volkswagen AG",
"exch": "PNK",
"type": "S",
"exchDisp": "OTC Markets",
"typeDisp": "Equity"
},
{
"symbol": "VOW3.DE",
"name": "Volkswagen AG",
"exch": "GER",
"type": "S",
"exchDisp": "XETRA",
"typeDisp": "Equity"
},
{
"symbol": "VOW.DE",
"name": "Volkswagen AG",
"exch": "GER",
"type": "S",
"exchDisp": "XETRA",
"typeDisp": "Equity"
}
]
}
}
What I got:
JavaScriptSerializer js = new JavaScriptSerializer();
string jsonString = "...String is here...";
SearchObj obj = js.Deserialize<SearchObj>(jsonString);
I understand that I usually have to create a fitting obj. e.g. SearchObj which will get filled but in this case I'm not entirely sure how this object is supposed to look like. I came up with:
class Data
{
public string symbol { get; set; }
public string name { get; set; }
public string exch { get; set; }
public string type { get; set; }
public string exchDisp { get; set; }
public string typeDisp { get; set; }
}
class Container
{
public string Query { get; set; }
public List<Data> Result { get; set; }
}
class SearchObj
{
public Container ResultSet { get; set; }
}
But guess what, it's not working, I only get ResultSet = null.

Try to change your class Container as
class Container
{
public string Query { get; set; }
public Data[] Result { get; set; }
}
I have not tested it, based on my observation

I always feel bad when I answer my own question but here it goes.
Basically my idea was correct, I only made one mistake which is that I don't need the
class SearchObj
{
public Container ResultSet { get; set; }
}
Using
Container obj = js.Deserialize<Container>(jsonString);
instead of
SearchObj obj = js.Deserialize<SearchObj>(jsonString);
made the trick. Both Data[] and List<Data> in Container work btw.
Edit:
From giammins comment it seems that it is working on some machines without that change but I guess that's a case for undefined behavior.

You can use http://www.json2charp.com to create your classes.

Related

Deserialize complex JSON object fails to see collection

I've simplified the code (below) but I cannot figure out why the Result.Data property is not getting filled; it is always null. I've used jsonlint.com to validate the JSON (both this small sample and the full content). I built a separate project (using How to Deserialize a Complex JSON Object in C# .NET) and it successfully serializes the complex object listed there. But I cannot get this one to work and I'm stumped.
using System.Text.Json;
namespace JsonTest2;
public class Result
{
public string? Total { get; set; }
public string? Limit { get; set; }
public string? Start { get; set; }
protected List<Park>? Data { get; set; }
}
public class Park
{
public string? Id { get; set; }
}
internal class Program
{
var basepath = AppDomain.CurrentDomain.BaseDirectory;
var filepath = basepath.Split("\\bin")[0];
var filename = #$"{filepath}\NPS_response_small.json";
var jsonstr = File.ReadAllText(filename);
var response = JsonSerializer.Deserialize<Result>(jsonstr, new JsonSerializerOptions() { PropertyNameCaseInsensitive = true });
}
This is the content of "NPS_response_small.json":
{
"total": "468",
"limit": "50",
"start": "0",
"data": [
{
"id": "77E0D7F0-1942-494A-ACE2-9004D2BDC59E"
},
{
"id": "6DA17C86-088E-4B4D-B862-7C1BD5CF236B"
},
{
"id": "E4C7784E-66A0-4D44-87D0-3E072F5FEF43"
}
]
}
you have to chanbe a protected attribute of property Data to a public. Json deserializer doesnt have any acces to this property
public List<Park>? Data { get; set; }
it would be much easier to use Newtonsoft.Json, but if you need protected for some reason, you can try this ( but I am not sure that it is a full replacement)
public List<Park>? Data { protected get; init ; }
[System.Text.Json.Serialization.JsonConstructor]
public Result (List<Park>? Data, string? Total, string? Limit, string? Start)
{
this.Data=Data;
this.Total=Total;
this.Limit=Limit;
this.Start=Start;
}

C# Newtonsoft deserialize JSON array

I'm trying to deserialize an array using Newtonsoft so i can display files from a cloud based server in a listbox but i always end up getting this error no matter what i try:
Newtonsoft.Json.JsonReaderException: 'Unexpected character encountered while parsing value: [. Path '[0].priv', line 4, position 15.'
Thisis an example try to deserialize:
[
{
"code": 200,
"priv": [
{
"file": "file.txt",
"ext": "txt",
"size": "104.86"
},
{
"file": "file2.exe",
"ext": "exe",
"size": "173.74"
},
],
"pub": [
{
"file": "file.txt",
"ext": "txt",
"size": "104.86"
},
{
"file": "file2.exe",
"ext": "exe",
"size": "173.74"
}
]
}
]
I tried using a C# Class like this:
public class ListJson
{
[JsonProperty("pub")]
public List List { get; set; }
}
public class List
{
[JsonProperty("file")]
public string File { get; set; }
[JsonProperty("ext")]
public string Ext { get; set; }
[JsonProperty("size")]
public string Size { get; set; }
}
[JsonProperty("priv")]
public List List { get; set; }
}
public class List
{
[JsonProperty("file")]
public string File { get; set; }
[JsonProperty("ext")]
public string Ext { get; set; }
[JsonProperty("size")]
public string Size { get; set; }
}
And deserialize with:
List<list> fetch = Newtonsoft.Json.JsonConvert.DeserializeObject<List<list>>(json);
The correct C# class structure for your JSON is the following:
public class FileEntry
{
public string file { get; set; }
public string ext { get; set; }
public string size { get; set; }
}
public class FileList
{
public int code { get; set; }
public List<FileEntry> priv { get; set; }
public List<FileEntry> pub { get; set; }
}
Deserializing it in this way:
var fetch = JsonConvert.DeserializeObject<FileList[]>(json);
var fileList = fetch.First(); // here we have a single FileList object
As said in the other answer, creating a class called List doesn't automagically turn it into a collection of objects. You need to declare the types to be deserialized from an array a collection type (e.g. List<T>, T[], etc.).
Small tip: when in doubt, use json2csharp.com to generate strongly typed classes from a json string.
At the moment List has a single List instance called priv, which despite the name: doesn't make it a list. To deserialize a JSON array ("priv": [...]), it needs to an array or list-like type, for example List<T> for some T. Presumably a List<FileThing>, if we assume that FileThing is actually the second type called List (you have 2).

xamarin c# deserialize Json containing nested object

I have a webservice that return a Json in this format :
[{
"Route0": {
"RouteID": "AAA",
"RouteDescription": "",
"ReturnCode": "0",
"ReturnError": ""
}
}, {
"Route1": {
"RouteID": "AABCLO",
"RouteDescription": "Antoine Abdo Bachaalani Close",
"ReturnCode": "0",
"ReturnError": ""
}
}]
I need to deserialize it:
I created 2 class:
public class PullRouteDetailsObjectChild
{
public string RouteID { get; set; }
public string RouteDescription { get; set; }
public string ReturnCode { get; set; }
public string ReturnError { get; set; }
}
public class PullRouteDetailsObject
{
public PullRouteDetailsObjectChild Route { get; set; }
}
and I am using this code to deserialize:
List<PullRouteDetailsObject> jsonRoutes =
JsonConvert.DeserializeObject<List<PullRouteDetailsObject>>(jsonresult);
I am able to get a list of 2 PullRouteDetailsObject wich is correct but the child object is always null.
I am sure that I am missing something but can't find what. I need to access child object
Thank you for your help.
You need to use this instead:
var jsonRoutes = JsonConvert.DeserializeObject<List<Dictionary<string, PullRouteDetailsObject>>>(jsonresult);
As you're getting a list of objects with a property which contains your 'PullRouteDetailsObject' (Route0, Route1).

Deserialize nested Json data with Newtonsoft in C# and assign into variable

Here is the Json data that I got
{
"Data": {
"namelist": [
{
"name": "Elson Mon",
"Information": {
"Age": 45.0,
"Height": 168.7,
"Weight": 75.4,
"Birthdate": "1992-03-03"
},
"Married Status": "Single"
}
]
}
}
And here are my models
public class Information
{
public double Age { get; set; }
public double Height { get; set; }
public double Weight { get; set; }
public string Birthdate { get; set; }
}
public class Namelist
{
public string name { get; set; }
public Information Information { get; set; }
public string MarriedStatus { get; set; }
}
public class Data
{
public List<Namelist> namelist { get; set; }
}
public class RootObject
{
public Data Data { get; set; }
}
How can I deserialize the Json format string and assign into variable ?
I'm trying to use
dynamic jsonResponse = JsonConvert.DeserializeObject<RootObject>(json);
to deserialize the Json data but have totally no idea on how to assign it into different variable.
Am I right in assuming your problem is actually assigning the result to a variable?
If that's the case, you needn't bother figuring out the type (although it's pretty obvious here - you're deserializing a string into RootObject, so if this works, you'll naturally have a RootObject). Just let the compiler do it for you:
var jsonResponse = JsonConvert.DeserializeObject<RootObject>(json);
You can then hover over "var" to see the type. It's much more convenient when you really have no idea what you're working with or if the type is something rather ugly like IEnumerable<KeyValuePair<int, List<string>>>.
Avoid the dynamic type in such cases; always prefer putting the actual type or "var". The compiler doesn't know what you've got if you store it in a dynamic, so it won't issue any warnings if you're using your object in an inappropriate way, you'll face the consequences run-time.
You are in the right path.
RootObject obj = JsonConvert.DeserializeObject<RootObject>(json);
Example:
public static void Main(string[] args)
{
string json = #"{
'Data': {
'namelist': [
{
'name': 'Elson Mon',
'Information': {
'Age': 45.0,
'Height': 168.7,
'Weight': 75.4,
'Birthdate': '1992-03-03'
},
'Married Status': 'Single'
}
]
}
}";
RootObject obj = JsonConvert.DeserializeObject<RootObject>(json);
}

deserializing child data collections into ienumerables using JSON.NET

Current I have a project where I'm getting the following sample data ( I want to retrieve only the ids within this json string and stuff them into IEnumerables (explained below):
{
"states": [
{
"id": "AL",
"text": "Alabama (AL)"
},
{
"id": "CO",
"text": "Colorado (CO)"
}
],
"cities": [
{
"id": 71761,
"text": "New Brockton, AL"
},
{
"id": 74988,
"text": "Nathrop, CO"
}
],
"zipCodes": []
}
Notice in the zipCodes, I am getting an empty set, so there is no "id" or "text".
I want to be able to create several IEnumerables from the properties found in this JSON string.
I created an object called Locations that looks like this:
public class Location
{
public IEnumerable<string> States { get; set; }
public IEnumerable<string> ZipCodes { get; set; }
public IEnumerable<decimal> Cities { get; set; }
}
The best way I found to going about this approach is to do each data property one by one and convert, formValues is the json string:
JArray arrStates = (JArray)formValues["states"];
JArray arrCities = (JArray)formValues["cities"];
JArray arrZip = (JArray)formValues["zipCodes"];
and then set the properties in the location object as so:
Location loc = new Location();
loc.States = arrStates.Children().Select(m=>m["id"].Value<string>());
loc.ZipCodes = arrCities.Children().Select(m=>m["id"].Value<string>());
loc.Cities = arrZip.Children().Select(m=>m["id"].Value<string>());
I was wondering if there's a better way of doing this instead of doing all this code maintenance for whenever my json response adds a new property. In fact, I think there's going to be about ten more properties added to the json string.
I want it to be reduced down to where I could just update the Location object, and have the json automatically map to the properties that way. Or atleast a solution that has less maintenance than what I'm doing now.
Also I was wondering if JsonConvert.DeserializeObject would work in my case; but read that JSON.NET treats an IEnumerable as an array, so I'm stumped on this one.
JsonConvert.DeserializeObject would work in your case and it will have less maintenance than what you're doing now.
If you enter your json data to http://json2csharp.com, below is the generated class definition that you can use, I renamed RootObject to Location
public class State
{
public string id { get; set; }
public string text { get; set; }
}
public class City
{
public int id { get; set; }
public string text { get; set; }
}
public class Location
{
public List<State> states { get; set; }
public List<City> cities { get; set; }
public List<object> zipCodes { get; set; }
}
This is how you deserialize the json data into Location
string jsonData = ...; // set the json data here
var location = JsonConvert.DeserializeObject<Location>(jsonData);
You can enumerate through the nested properties to get the ids, for example location.states[0].id will return "AL" and location.cities[1].id will return 74988.
If there's a new property in the json data, let's say it's named countries with id and text like in states, you can create a new Country class
public class Country
{
public string id { get; set; }
public string text { get; set; }
}
and add countries property to Location class
public class Location
{
public List<State> states { get; set; }
public List<City> cities { get; set; }
public List<object> zipCodes { get; set; }
public List<Country> countries { get; set; }
}

Categories

Resources