简体   繁体   中英

Converting JSON object to dictionary

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM