I'm having a bit of trouble with C# (VS 2017, .Net 4.6) code. It'd be great if someone could help. I have a JSON file:
{
"makerCommission": 10,
"takerCommission": 10,
"buyerCommission": 0,
"updateTime": 1540015045989,
"balances": [
{
"asset": "BTC",
"free": "0.22222222",
"locked": "0.00000000"
},
{
"asset": "LTC",
"free": "2.00000000",
"locked": "3.00000000"
},
{
"asset": "ETH",
"free": "4.00000000",
"locked": "5.00000000"
}
]
}
I would like to retrieve the "free" value of any coin using:
result = (dynamic)JArray.Parse(MyData)
I do not want to retrieve all free values. How can I get 0.22222222, if I pick BTC?
First of all, your overall JSON does not represent an array, it represents an object which contains an array. So you would need to use JObject.Parse instead of JArray.Parse.
You can use the following LINQ-to-JSON code to find a specific asset in the array and then get the free value from it:
JObject obj = JObject.Parse(json); // Parse the JSON to a JObject
string free = obj["balances"] // Navigate down to the "balances" array
.Where(jt => (string)jt["asset"] == "BTC") // Find the object(s) containing the asset you want
.Select(jt => (string)jt["free"]) // From those get the "free" value
.FirstOrDefault(); // Take the first of those
Fiddle: https://dotnetfiddle.net/uFjSib
You are almost there. You have a JSON object, that contains the array, so you need to parse first the Object and then access the array using the name balances.
var result = (dynamic)JObject.Parse(MyData);
Console.WriteLine(result.balances); // output JArray ...
You can then get the value from the array like this:
Console.WriteLine(String.Format("{0} - {1}", result.balances[2].asset, result.balances[2].free));
The output is the third element from the array:
ETH - 4.00000000
In order to get only the BTC entry you need to filter the array:
foreach (var balance in result.balances)
{
if (balance.asset == "BTC")
{
Console.WriteLine(balance.free);
}
}
A better approach would be to create a class that represents the object structure and parse it. The filtering then will be easier using LINQ:
public class BalanceItem
{
public string asset { get; set; }
public double free { get; set; }
public double locked { get; set; }
}
public class Items
{
public List<BalanceItem> balances { get; set; }
}
var items = JsonConvert.DeserializeObject<Items>(MyData);
var btc = items.balances.FirstOrDefault (b => b.asset == "BTC");
if (btc != null)
{
Console.WriteLine(btc.free);
}
The output is: 0.22222222
Alternatively, you could use JToken
The following script gives you the wanted value. Maybe not the conceptually finest approach, but really intuitive.
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
public class Program
{
public static void Main()
{
string json = #"
{
""makerCommission"": 10,
""takerCommission"": 10,
""buyerCommission"": 0,
""updateTime"": 1540015045989,
""balances"": [
{
""asset"": ""BTC"",
""free"": ""0.22222222"",
""locked"": ""0.00000000""
},
{
""asset"": ""LTC"",
""free"": ""2.00000000"",
""locked"": ""3.00000000""
},
{
""asset"": ""ETH"",
""free"": ""4.00000000"",
""locked"": ""5.00000000""
}
]
}";
var value = "";
JToken token = JToken.Parse(json);
var balances = token.SelectToken("balances");
foreach(var balance in balances){
if((string)balance.SelectToken("asset") == "BTC"){
value = (string)balance.SelectToken("free");
}
}
Console.WriteLine("value: " + value);
}
}
Inspired by this post
I have a below Jason format in which the Claims will be a array collection now I need to read all the Claims(which is a collection in below json) related to the policyid from c# , could anyone help me resoling it
{
"ClaimList": [{
"Claims": ["CL8901"],
"PolicyID": "W1234sd",
"ClaimsCount": 1
}, {
"Claims": ["CL3456", "CL1234"],
"PolicyID": "T1234sd",
"ClaimsCount": 2
}, {
"Claims": ["CL1321"],
"PolicyID": "C1234sd",
"ClaimsCount": 1
}]
}
string json = Util.ReadLine<string>();
JObject.Parse(json).SelectToken("ClaimList").Select(cl => new
{
PolicyId = cl.SelectToken("PolicyID"),
Claims = cl.SelectToken("Claims").ToObject<List<string>>()
}).Dump();
Linqpad code
http://share.linqpad.net/vqoav5.linq
To achieve what you need, do the following:
Follow my answer here to create C# classes for your json
Use NewtonSoft NuGet library to deserialize the JSON to C# objects
Perform whatever processing you need on the deserialized items
Here is some code once you have done the above:
var claims = JsonConvert.DeserializeObject<Rootobject>("YourJsonHere");
IEnumerable<Claimlist> claimsForPolicy=
claims.ClaimList.Where(x => x.PolicyID == "whateverYouNeed");
If you can use the Json.NET library (NuGet), this is pretty straightforward. First make sure you have a Claim class that has the structure of those inner objects in your JSON:
class Claim
{
public List<string> Claims { get; set; }
public string PolicyID { get; set; }
public int ClaimsCount { get; set; }
}
Having that class available, you can use Json.NET to do something like this:
using Newtonsoft.Json;
// ...
string yourJson = getYourJsonStringSomehow();
var claimsDict =
JsonConvert.DeserializeObject<Dictionary<string, List<Claim>>>(yourJson);
That will produce a Dictionary with one key: "ClaimsList", and the value will be a List of your Claim objects:
var claimsList = claimsDict["ClaimsList"];
var firstClaim = claimsList[0];
Console.WriteLine(firstClaim.PolicyID);
// Should print W1234sd
You can try this, first lets create a Json class for your json data:
public class JsonDoc
{
//I am adding an index on constructor for looping purposes
public JsonDoc(string json, int index)
{
JObject jObject = JObject.Parse(json);
JToken jResult = jObject["ClaimList"];
Claims = jResult[index]["Claims"].ToObject<string[]>();
}
//This constructor will return the number of count under ClaimList node
public JsonDoc(string json)
{
JObject jObject = JObject.Parse(json);
JToken jResult = jObject["ClaimList"][0];
intCount = jResult.Count();
}
private string[] Claims { get; set; }
public int intCount { get; set; }
}
Then to use this class for your Json data, first add a reference of Newtonsoft Json.
using Newtonsoft.Json.Linq;
Then on your sample data, I read all the data via file using StreamReader, loop on it and put all the data under a List:
private static void Main(string[] args)
{
using (StreamReader sr = new StreamReader(#"C:\Folder\myjson.json"))
{
string json = sr.ReadToEnd();
JsonDoc jSon = new JsonDoc(json);
//This will get the length of the array under ClaimList node
int intCount = jSon.intCount;
List<JsonDoc> lstResult = new List<JsonDoc>();
for (int x = 0; x < intCount; x++)
{
lstResult.Add(new JsonDoc(json, x));
}
}
}
The result is a List of JsonDoc class with array of string as part of property. This array of string is the result on your Claims Node. This JsonDoc class contains property Claims which is a string array which contains your Claims node:
I want following JSON result to use in highstock pie chart.
[['John', 63.0163],['Depp', 19.2422],['Carla', 6.4767],['Santa', 0],['Tim', 11.2647]]
I tried to make List<ChartSeries> of below object having string and double properties
public class ChartSeries
{
public string Person { get; set; }
public double Percent { get; set; }
}
but using Newtonsoft.JSON it serialize and give below result which shows class properties names which will not be accepted by highstock pie chart.
[{"Person":"John", "Percent":63.0163},{"Person":"Depp", "Percent":19.2422},{"Person":"Carla", "Percent":6.4767},{"Person":"Santa", "Percent":0},{"Person":"Tim", "Percent":11.2647}]
Thanks in advance
Try transforming your data and serializing the output.
internal static class Extensions
{
public static IEnumerable<dynamic> Transform(this IEnumerable<ChartSeries> data)
{
foreach (var chartSeries in data)
{
var result = new ExpandoObject() as IDictionary<string, object>;
result.Add(chartSeries.Person, chartSeries.Percent);
yield return result;
}
}
}
Haven't tried it but serializing the dynamics collection should do the trick.
I'm getting an irregular JSON array from the Census Bureau's public api.
The variable names are all in the first element, and I'm having trouble deserializing it.
http://api.census.gov/data/2014/pep/agesex?get=AGE,POP,SEX&for=us:*&DATE=7
gives me JSON like this:
[["AGE","POP","SEX","DATE","us"],
["0","3948350","0","7","1"],
["1","3962123","0","7","1"],
["2","3957772","0","7","1"],
["3","4005190","0","7","1"],
["4","4003448","0","7","1"],
["5","4004858","0","7","1"],
["6","4134352","0","7","1"],
["7","4154000","0","7","1"]]
I can successfully deserialize this using:
var test1 = JsonConvert.DeserializeObject<String[][]>(jsonStr);
However, I'm trying to deserialize it to a class like this:
public class TestClass
{
public string AGE { get; set; }
public string POP { get; set; }
public string SEX { get; set; }
public string DATE { get; set; }
public string us { get; set; }
}
I'm trying to do this:
var test2 = JsonConvert.DeserializeObject<TestClass[]>(jsonStr);
But I'm getting the following exception:
An exception of type 'Newtonsoft.Json.JsonSerializationException'
occurred in Newtonsoft.Json.dll but was not handled in user code
Additional information: Cannot create and populate list type
TestClass. Path '[0]', line 1, position
2.
There's two parts to this.
First is turning the JSON in to data usable in C#, and the second is turning that data in to nice objects.
Here's a working dotNetFiddle.net example of the following code: https://dotnetfiddle.net/Cr0aRL
Each row in your JSON is made up of an array of strings.
So that's an array of an array of strings.
In C# that can be written as string[][].
So to turn the JSON in to usable data with JSON.Net you can do:
var json = "[[\"AGE\",\"POP\",\"SEX\",\"DATE\",\"us\"],[\"0\",\"3948350\",\"0\",\"7\",\"1\"],[\"1\",\"3962123\",\"0\",\"7\",\"1\"],[\"2\",\"3957772\",\"0\",\"7\",\"1\"],[\"3\",\"4005190\",\"0\",\"7\",\"1\"],[\"4\",\"4003448\",\"0\",\"7\",\"1\"],[\"5\",\"4004858\",\"0\",\"7\",\"1\"],[\"6\",\"4134352\",\"0\",\"7\",\"1\"],[\"7\",\"4154000\",\"0\",\"7\",\"1\"]]";
var rawData = JsonConvert.DeserializeObject<string[][]>(json);
Next up is is turning that data in to objects.
The first row is the header, containing the column names, so we want to grab that, and then figure out the column index for each column name.
var headerRow = rawData.First();
var ageIndex = Array.IndexOf(headerRow, "AGE");
var popIndex = Array.IndexOf(headerRow, "POP");
var sexIndex = Array.IndexOf(headerRow, "SEX");
var dateIndex = Array.IndexOf(headerRow, "DATE");
var usIndex = Array.IndexOf(headerRow, "us");
Now we have the indexes, we need to take each row, and convert it in to the appropriate object. I've used LINQ for this as it's very good at representing data processing in a clear way.
var testData = rawData
.Skip(1) //The first row is a header, not data
.Select(dataRow => new TestClass()
{
AGE = dataRow[ageIndex],
POP = dataRow[popIndex],
SEX = dataRow[sexIndex],
DATE = dataRow[dateIndex],
us = dataRow[usIndex]
});
Finally a bit of testing, to make sure you have the data you're expecting.
//Get the second data row as an example
var example = testData.Skip(1).First();
//Output example POP to check value
Console.WriteLine(example.POP);
Everything above is very manual.
You have to know what headers you expect, then you manually find the indexes, then you manually map the rows to objects.
It's quite possible for a simple use case that doing that is fine. But in larger and/or more complex systems you might want/need to automate those steps.
Automating those steps is possible, but is beyond the scope of this answer as how you approach it can depend on a lot of different factors.
You could make a custom JsonConverter to handle this conversion during deserialization. The conversion code is really not much different than other answers here, except that it is encapsulated into a separate class so that you don't muddy up your main code with the conversion details. From the point of view of your main code it "just works".
Here is how to write the converter:
public class TestClassArrayConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(TestClass[]));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JArray table = JArray.Load(reader);
TestClass[] items = new TestClass[table.Count - 1];
for (int i = 1; i < table.Count; i++)
{
JArray row = (JArray)table[i];
items[i - 1] = new TestClass
{
AGE = (string)row[0],
POP = (string)row[1],
SEX = (string)row[2],
DATE = (string)row[3],
us = (string)row[4]
};
}
return items;
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
And here is how you would use it:
var test2 = JsonConvert.DeserializeObject<TestClass[]>(jsonStr, new TestClassArrayConverter());
Fiddle: https://dotnetfiddle.net/68Q0KT
You have to do the processing on your own, as there is no way the json deserializer can know, how to put the values into the respecitve variables.
If you know, this will be exactly this structure, you could for instance add an appropriate constructor
public TestClass(string[] values) {
AGE = values[0];
...
}
to your class. Then serialize your result to array of arrays of string and then pass the inner arrays to your constructor.
var t1 = JsonConvert.DeserializeObject<string[][]>(jsonStr);
//skip the first entry, as this contains the headers
var t2 = t1.Skip(1).Select(x=> new TestClass(x));
If your structure varies, you'll have to write some more complicated mapping code.
You will have to do some custom mapping as your Json does not have any naming conventions so you will have to work with the data in array and index formats. This will work:
var jsonStr = "[[\"AGE\",\"POP\",\"SEX\",\"DATE\",\"us\"], [\"0\",\"3948350\",\"0\",\"7\",\"1\"], [\"1\",\"3962123\",\"0\",\"7\",\"1\"], [\"2\",\"3957772\",\"0\",\"7\",\"1\"], [\"3\",\"4005190\",\"0\",\"7\",\"1\"], [\"4\",\"4003448\",\"0\",\"7\",\"1\"], [\"5\",\"4004858\",\"0\",\"7\",\"1\"], [\"6\",\"4134352\",\"0\",\"7\",\"1\"], [\"7\",\"4154000\",\"0\",\"7\",\"1\"]]";
var test2 = JsonConvert.DeserializeObject<string[][]>(jsonStr);
var test3 = test2.Select(x => new TestClass()
{
AGE = x[0].ToString(),
POP = x[1].ToString(),
SEX = x[2].ToString(),
DATE = x[3].ToString(),
us = x[4].ToString()
}).ToList();
//test Case
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
namespace ApiController.Test
{
[TestClass]
public class DownloadIrregularJsonStringObjects
{
string ApiKey => "YourPersonalCensusKey";
/// <summary>
/// You have to get your own ApiKey from the Census Website
/// </summary>
[TestMethod]
public void TestGetItem()
{
string url = $"http://api.census.gov/data/timeseries/healthins/sahie?get=NIC_PT,NAME,NUI_PT&for=county:*&in=state:*&time=2015&key={YourPersonalCensusKey}";
string expected = "Autauga County, AL";
IList<HealthData> actual = ApiController.DownloadIrregularJsonStringObjects.GetCensusHealthData(url);
Assert.AreEqual(actual[0].NAME, expected);
}
}
}
///Actual Assembly
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
namespace ApiController
{
public class DownloadIrregularJsonStringObjects
{
public static IList<HealthData> GetCensusHealthData(string url)
{
var json = GetData(url);
var rawData = JsonConvert.DeserializeObject<string[][]>(json);
var headerRow = rawData.First();
var nic_pt_Index = Array.IndexOf(headerRow, "NIC_PT");
var name_Index = Array.IndexOf(headerRow, "NAME");
var nui_pt_Index = Array.IndexOf(headerRow, "NUI_PT");
IList<HealthData> retVal = new List<HealthData>();
foreach (var r in rawData.Skip(1))
{
HealthData dataRow = new HealthData();
dataRow.NIC_PT = r[nic_pt_Index];
dataRow.NAME = r[name_Index];
dataRow.NUI_PT = r[nui_pt_Index];
retVal.Add(dataRow);
}
return retVal;
}
private static string GetData(string url)
{
using (var w = new WebClient())
{
var jsonData = string.Empty;
jsonData = w.DownloadString(url);
return jsonData;
}
}
}
public class HealthData
{
public string NIC_PT { get; set; }
public string NAME { get; set; }
public string NUI_PT { get; set; }
}
}
I am having some trouble deserializing a Json string to use in an api wrapper I am currently writing. This is the json string in question:
{
"Search":[
{
"Title":"Clerks.",
"Year":"1994",
"imdbID":"tt0109445",
"Type":"movie"
},
{
"Title":"Clerks II",
"Year":"2006",
"imdbID":"tt0424345",
"Type":"movie"
}
]
}
This is the method I am currently using to process it.
public static Dictionary<string, string> FetchTitlesListDictionary(string searchQuery)
{
string searchResult = SendRequest(new[] { "?s=", searchQuery });
JObject parser = JObject.Parse(searchResult);
var movieDictionary = new Dictionary<string, string>();
for (int i = 0; i < parser["Search"].Count(); i++)
{
if (!movieDictionary.ContainsKey((string)parser["Search"][i]["imdbID"]))
{
movieDictionary.Add((string)parser["Search"][i]["imdbID"],
(string)parser["Search"][i]["Title"]);
}
}
return movieDictionary;
}
Even though the code above works, I feel it could, somehow, be made simpler.
How would I go about achieving this?
Thanks!
var obj = JsonConvert.DeserializeObject<RootObject>(searchResult);
public class Search
{
public string Title { get; set; }
public string Year { get; set; }
public string imdbID { get; set; }
public string Type { get; set; }
}
public class RootObject
{
public List<Search> Search { get; set; }
}
If you really want to convert the RootObject to a dictionary, you can use
var movieDictionary = obj.Search.ToDictionary(s => s.imdbID, s => s.Title);
PS: see this site
Well, if you're open to not using the default serializer, I would just open up the package manager console and type
Install-Package ServiceStack.Text
Then it becomes as easy as
var myDictionary = JsonObject.Parse(myJsonString)
.ArrayObjects("Search")
.ToDictionary(key => key.Get("imdbID"), value => value.Get("Title"));
There might be a similar and just as simple way to do it with the newtonsoft serializer, but honestly I never use it, so i'm not sure.
Also same thing as EZI's answer, it's also really easy if you have the objects he created, then you can just
var myObject = myJsonString.FromJson<RootObject>();
//if you want the dictionary it's the same thing, standard linq
var dictionary = myObject.Search.ToDictionary(x => x.imdbId, x => x.Title);
but if all you need is a dictionary, I would just use the above method, it's fast and easy.