Converting JSON object to dictionary - c#

I'm calling the ethplorer.io api, and it returns the below json. I have generated the classes in visual studio via 'paste special -> paste json as classes'. My problem is that Tokeninfo declares price as an object, this is because it can either be false if it has no price information, or a dictionary if it has values. While I have successfully deserialised the response using JsonConvert.DeserializeObject(rawJSON), I’m struggling to convert price in to c# dictionary if it has values.
public class Tokeninfo
{
public string address { get; set; }
public string name { get; set; }
public object decimals { get; set; }
public string symbol { get; set; }
public string totalSupply { get; set; }
public string owner { get; set; }
public long lastUpdated { get; set; }
public int issuancesCount { get; set; }
public int holdersCount { get; set; }
public object price { get; set; }
public string description { get; set; }
public float totalIn { get; set; }
public float totalOut { get; set; }
}
JSON response:
{
"address": "0xd8f41f341afe2c411b21b3f96263c6584b69baeb", //Not my address
"ETH": {
"balance": 762.13611095505,
"totalIn": 1040.0907032491,
"totalOut": 277.954592294
},
"countTxs": 22,
"tokens": [
{
"tokenInfo": {
"address": "0x355a458d555151d3b27f94227960ade1504e526a",
"name": "StockChain Coin",
"decimals": "18",
"symbol": "SCC",
"totalSupply": "10000000000000000000000000000",
"owner": "0x",
"lastUpdated": 1524401998,
"issuancesCount": 0,
"holdersCount": 86520,
"price": {
"rate": "0.0531126",
"diff": 4.8,
"diff7d": 19.82,
"ts": "1524400762",
"marketCapUsd": null,
"availableSupply": null,
"volume24h": "622004.0",
"currency": "USD"
}
},
"balance": 5000000000000000000,
"totalIn": 0,
"totalOut": 0
},
{
"tokenInfo": {
"address": "0xb679afd97bcbc7448c1b327795c3ef226b39f0e9",
"name": "Win Last Mile",
"decimals": "6",
"symbol": "WLM",
"totalSupply": "2000000000000000",
"owner": "0x8e7a75d5e7efe2981ac06a2c6d4ca8a987a44492",
"lastUpdated": 1524362946,
"issuancesCount": 0,
"holdersCount": 10945,
"price": false
},
"balance": 66000000,
"totalIn": 0,
"totalOut": 0
},
{
"tokenInfo": {
"address": "0xae66d00496aaa25418f829140bb259163c06986e",
"name": "Super Wallet Token",
"decimals": "8",
"symbol": "SW",
"totalSupply": "8400000000000000",
"owner": "0xba051682e9dbc40730fcef4a374e3a57a0ce3eff",
"lastUpdated": 1524401948,
"issuancesCount": 0,
"holdersCount": 30276,
"price": false
},
"balance": 11567900,
"totalIn": 0,
"totalOut": 0
},
{
"tokenInfo": {
"address": "0x8e4fbe2673e154fe9399166e03e18f87a5754420",
"name": "Universal Bonus Token | t.me/bubbletonebot",
"decimals": "18",
"symbol": "UBT",
"totalSupply": "1150000000000000000000000",
"owner": "0xc2db6e5b96dd22d9870a5ca0909cceac6604e21d",
"lastUpdated": 1524393745,
"issuancesCount": 0,
"holdersCount": 99896,
"price": false
},
"balance": 10000000000000000000,
"totalIn": 0,
"totalOut": 0
}
]
}

You need a custom deserializer to do what you want. It should be straight forward though. Here is some code which checks if the price is not false and then turns it into a Dictionary<string, string>. This code makes the assumption that your root object is named RootObject:
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var jsonObject = JObject.Load(reader);
var root = default(Rootobject);
// Let's go through each tokenInfo and check if price is not false
// so we can turn it into a dictionary.
foreach (var thisToken in root.tokens)
{
if (thisToken.tokenInfo.price.ToString() != "false")
{
thisToken.tokenInfo.price = JsonConvert.DeserializeObject<Dictionary<string, string>>(thisToken.tokenInfo.price.ToString());
}
}
serializer.Populate(jsonObject.CreateReader(), root);
return root;
}
Please see the full example here and search for ProfessionConverter in that link for the full class.

I think it is not very good approach to use false in cases when there is no price. If there is no price it should be something like "price" :{} or price element shouldn't be there at all. In other words, it is not good idea to mixup boolean object and dictionaty imho.
I think you can use provided by VisualStudio class where Price is an object. And you can create a custom serializer which will treat false as an null (or object with empty fields) along with standart deserialization mechanism.

Related

Nested item in json array is not being deserialized

I am trying to deserialize a json string from an api.
All works except for a nested item - Location which always ends up null
This is the string structure:
[
{
"CompanyProfile": "<p>A&B Inc etc...</p>",
"Address": "56 Test Street, Test, UK",
"Location": {
"Latitude": 61.52787,
"Longitude": -4.32095,
"Zoom": 13,
"Icon": null,
"Format": 0,
"Api": null,
"SearchTyped": null
},
"Id": 1723,
"Name": "A&B Inc"
},
{
"CompanyProfile": "<p>B&C Inc etc...</p>",
"Address": "57 Test Street, Test, UK",
"Location": {
"Latitude": 61.2122,
"Longitude": -4.31111,
"Zoom": 13,
"Icon": null,
"Format": 0,
"Api": null,
"SearchTyped": null
},
"Id": 1723,
"Name": "B&C Inc"
},
]
These are the classes to map to:
public class MemberDto
{
public int Id { get; set; }
public string? Name { get; set; }
public string? CompanyProfile { get; set; }
public string? Address { get; set; }
public Location? Location { get; internal set; }
}
public class Location
{
public decimal Latitude { get; set; }
public decimal Longitude { get; set; }
}
This is the deserialize code:
var result = await response.Content.ReadAsStringAsync();
var members = JsonConvert.DeserializeObject<List<MemberDto>>(result);
I know I can use ReadFromJsonAsync<List<MemberDto>>() as well but using ReadFromString so I can check the json before deserializing. Anyway the result is exactly the same for ReadFromJsonAsync.
Everything except Location is deserialized successfully
Anyone know what the issue is?
Remove the internal access modifier in the setter of Location.
public Location? Location { get; set; }

Create object of json when elements are variables

i need help for deserialize this json on C#.
{
"date": "2021-01-04T16:58:06-03:00",
"resultsInThisPage": 2,
"currentPage": 1,
"totalPages": 1,
"paymentOrders": {
"3AC525B8EF5F413D86CFDC9318E8B3F8": {
"code": "3AC525B8EF5F413D86CFDC9318E8B3F8",
"status": 5,
"amount": 3.00,
"grossAmount": 3,
"lastEventDate": "2021-01-04T16:54:36-03:00",
"schedulingDate": "2021-01-04T16:54:31-03:00",
"transactions": [
{
"code": "AF63C1B13EF14F318C51119CBE1E5CA4",
"date": "2021-01-04T16:54:32-03:00",
"status": 3
}
],
"discount": {
"type": "DISCOUNT_PERCENT",
"value": 0
}
},
"1E5A8F8D35D34938A12281BD45C62DBE": {
"code": "1E5A8F8D35D34938A12281BD45C62DBE",
"status": 1,
"amount": 3.00,
"grossAmount": 0,
"lastEventDate": "2021-01-04T16:54:33-03:00",
"schedulingDate": "2021-02-04T05:54:31-03:00",
"transactions": [],
"discount": {
"type": "DISCOUNT_PERCENT",
"value": 0
}
}
}
}
I´m trying use one Class for make this, but the elements of "paymentOrders" are variables.
How is the best way for do this?
I need create a object to manipulate these values.
paymentOrders would be a Dictionary<string,SomeObject> where SomeObject represents the object with all the properties like code, status etc
You can use Dictionary<string, SomeType> (or even Dictionary<Guid, SomeType> in your case, based on provided sample) to represent dynamic property names for paymentOrders json object. Something like this should do the trick:
public class Root {
// your dynamic prop
public Dictionary<string, PaymentOrder> paymentOrders { get; set; }
public DateTime date { get; set; }
// ... the rest o properties
}
public class PaymentOrder {
public string code { get; set; }
public int status { get; set; }
// ... the rest o properties
}

Deserializing JSON Class with multiple Objects with different types

I am trying to deserialize the following string output to json in csharp.
Now the Problem is, that there are multiple objects that i dont know how to access.
My endgoal would be to access for example just the twitch object.
How would my Jsonclass need to look like?
Thanks in advance.
[
{
"type": "battlenet",
"id": "zzzz#25589",
"name": "zzzz#25589",
"visibility": 1,
"friend_sync": false,
"show_activity": true,
"verified": true
},
{
"type": "steam",
"id": "45356364364564",
"name": "zzzz",
"visibility": 1,
"friend_sync": false,
"show_activity": true,
"verified": true
},
{
"type": "twitch",
"id": "4353454353453",
"name": "zzzzz",
"visibility": 1,
"friend_sync": false,
"show_activity": true,
"verified": true
},
{
"type": "youtube",
"id": "xxxxx-xxxxxx",
"name": "Salt",
"visibility": 1,
"friend_sync": false,
"show_activity": true,
"verified": true
}
]
What you have here is a JSON array of objects. You have to parse it to an array or List :
Your object :
public class SomeObject
{
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("visibility")]
public int Visibility { get; set; }
[JsonProperty("friend_sync")]
public bool FriendSync { get; set; }
[JsonProperty("show_activity")]
public bool ShowActivity { get; set; }
[JsonProperty("verified")]
public bool Verified { get; set; }
}
Parsing :
var resultList = JsonConvert.DeserializeObject<List<SomeObject>>(jsonstring);
Then, just search for the twitch object :
resultList.FirstOrDefault(x=>x.type == "twitch")
Maybe I'm on the wrong path right now,
but since they've got all the same attributes why don't you try implement an Interface/Superclass and use Reflection to get the correct Type according to the value in "type" ?
To get the instance:
public object GetInstance(string typeString)
{
Type t = Type.GetType(typeString);
return Activator.CreateInstance(t);
}

Convert an List<object>to user defined class

I have some data that is object IEnumerable, how to do I convert it into class type, the name of class is option
"option": {
"id": 8204,
"name": "250 ML",
"price": 40.0,
"status": 1,
"archive": 0
}
"option": {
"id": 8204,
"name": "250 ML",
"price": 40.0,
"status": 1,
"archive": 0
}
class Option
{
public long Id { get; set; }
public string Name { get; set; }
public long Price { get; set; }
public long Status { get; set; }
public long Archive { get; set; }
}
so far tried =>
foreach (var VARIABLE_3 in (IEnumerable) VARIABLE_2)
{
if ( VARIABLE_3.ToString().Contains("option") && !VARIABLE_3.ToString().Contains("options"))
{
object[] values = ((IEnumerable)VARIABLE_3).Cast<object>().ToArray();
//Option[] values = VARIABLE_3.ToString().Cast<Option>().ToArray();
foreach (var VARIABLE in values)
{
strStringBuilder.Append("VARIABLE: " + VARIABLE + "\n");
}
}
}
Use JavascriptSerializer or Json.Net serializer to serialize or deserialize Json string.
string jsonArrayObject = #"
[
{ "id": 8204,
"name": "250 ML",
"price": 40.0,
"status": 1,
"archive": 0
},
{
"id": 8208,
"name": "Coke",
"price": 0.0,
"status": 1,
"archive": 0
}
]";
Javascript Serializer
List<Option> optionList = new System.Web.Script.Serialization.
JavaScriptSerializer().Deserialize<List<Option>>(jsonArrayObject);
Json.Net
List<Option> optionList = JsonConvert.DeserializeObject<List<Option>>(jsonArrayObject);

Cannot deserialize the current JSON array

First: I'm new to using JSON, and I used the answers on here to use Json.Net to deserialize data from a Pokemon API into a C# class (Pokemon class). I used http://json2csharp.com to help me define my class and it looks like this:
public class Pokemon
{
public Pokemon(string json)
{
JsonConvert.PopulateObject(json, this, PokeApi.JsonSerializerSettings);
}
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("evolutions")]
public Evolutions evolutions { get; set; }
[JsonProperty("national_id")]
public int national_id { get; set; }
}
with a bunch of other properties like resource_uri, attack stat, etc.
As the answer offered on the aforementioned link said, I used JsonConvert.DeserializeObject(json) like so:
public Pokemon GetPokemon(int nationalId)
{
using (WebClient client = new WebClient())
{
var json = client.DownloadString("http://pokeapi.co/api/v1/pokemon/" + nationalId + "/");
var output = JsonConvert.DeserializeObject<Pokemon>(json);
return output;
}
}
However I keep getting an exception that says "Cannot deserialize the current JSON array (e.g.[1,2,3]) into type 'Evolutions' because the type requires a JSON object..."
I found a lot of other questions asking the same exact thing, but I was confused with the top answers - sometimes the answer was to use JsonProperty, sometimes it was to use JsonConverter, without really an explanation on what all these meant. Do I need both?
Edit: sample json (call: http://pokeapi.co/api/v1/pokemon/1/)
{
"abilities": [
{
"name": "overgrow",
"resource_uri": "/api/v1/ability/1/"
},
{
"name": "chlorophyll",
"resource_uri": "/api/v1/ability/2/"
}
],
"attack": 49,
"catch_rate": 45,
"created": "2013-11-02T12:08:25.745455",
"defense": 49,
"egg_cycles": 21,
"egg_groups": [
{
"name": "Monster",
"resource_uri": "/api/v1/egg/1/"
},
{
"name": "Grass",
"resource_uri": "/api/v1/egg/8/"
}
],
"ev_yield": "1 Sp Atk",
"evolutions": {
"level": 16,
"method": "level up",
"resource_uri": "/api/v1/pokemon/2/",
"to": "Ivysaur"
},
"exp": 64,
"growth_rate": "ms",
"happiness": 70,
"height": "2'4",
"hp": 45,
"male_female_ratio": "87.5/12.5",
"modified": "2013-11-02T13:28:04.914889",
"moves": [
{
"learn_type": "other",
"name": "Tackle",
"resource_uri": "/api/v1/move/1/"
},
{
"learn_type": "other",
"name": "Growl",
"resource_uri": "/api/v1/move/2/"
},
{
"learn_type": "level up",
"level": 10,
"name": "Vine whip",
"resource_uri": "/api/v1/move/3/"
}
],
"name": "Bulbasaur",
"national_id": 1,
"resource_uri": "/api/v1/pokemon/4/",
"sp_atk": 65,
"sp_def": 65,
"species": "seed pokemon",
"speed": 45,
"total": 318,
"types": [
{
"name": "grass",
"resource_uri": "/api/v1/type/5/"
},
{
"name": "poison",
"resource_uri": "/api/v1/type/8/"
}
],
"weight": "15.2lbs"
}
Evolutions class:
public class Evolutions
{
public int level { get; set; }
public string method { get; set; }
public string resource_uri { get; set; }
public string to { get; set; }
}
I tried http://json2csharp.com/ with http://pokeapi.co/api/v1/pokemon/19/ and what I see is
public class RootObject
{
//...
public List<Evolution> evolutions { get; set; }
//...
}
This pretty mush is your Pokemon class. So you need to declare Evolutions as list.

Categories