How to select an element's value from a JArray - c#

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

Related

How do I parse a JProperty to retreive nested values with variable keys

Given I have a JObject:
{
"results": {
"payroll_report": {
"314568": {
"user_id": 314568,
"client_id": "484781",
"start_date": "2020-03-29",
"end_date": "2020-04-04",
"total_re_seconds": 49260,
"total_pto_seconds": 94716,
"total_work_seconds": 143976,
"total_paid_break_seconds": 0,
"total_unpaid_break_seconds": 0,
"pto_seconds": {
"22322828": 57348,
"12597955": 37368
},
"total_ot_seconds": 0,
"total_dt_seconds": 0,
"timesheet_count": 16
}
}
},
}
How do I parse it so I can know the number of pto_seconds for 22322828?
I am already able to get total_pro_seconds and other elements at that level, but I can't figure out how to get the nested values.
My assumption is you want to access all the nested Key-Value pairs under the pto_seconds element and assume that json structure is always as it was given on the example.
Here is the full code to iterate over the list and get values. My second assumption is values are long type, that is why I used jToken.First().Value<long>(). If it is decimal or other types you can change it accordingly.
var jObject = JsonConvert.DeserializeObject<JObject>(json);
var jTokenList = jObject["results"]["payroll_report"]["314568"]["pto_seconds"].Children().ToList();
foreach (var jToken in jTokenList)
{
var ptoSecondKey = (jToken as JProperty).Name;
var ptoSecondValue = jToken.First().Value<long>();
}
Alternative method(without using JObject):
You can have real object representation of your JSON structure and you can use DeserializeObject<T> method to parse and return results as your object.
Here below you can find classes for your JSON:
public class ResultsMain
{
[JsonProperty("results")]
public ResultsDetail Results { get; set; }
}
public class ResultsDetail
{
[JsonProperty("payroll_report")]
public PayrollReport PayrollReport { get; set; }
}
public class PayrollReport
{
[JsonProperty("314568")]
public PayrollReportDetail Detail { get; set; }
}
public class PayrollReportDetail
{
[JsonProperty("pto_seconds")]
public Dictionary<string, long> PtoSeconds { get; set; }
}
To deserialize the JSON to your .NET type, you need below one line of code:
var resultsMain = JsonConvert.DeserializeObject<ResultsMain>(json);
Here is a snapshot of resultMain object:
You can enumerate over JObject, (if your initial JObject is named jObject)
var toEnumerate = (JObject)(jObject["results"]["payroll_report"]["314568"]["pto_seconds"]);
foreach(var pair in toEnumerate)
{
Console.WriteLine("Key: " + pair.Key);
Console.WriteLine("Value: " + pair.Value);
}
output:
Key: 22322828
Value: 57348
Key: 12597955
Value: 37368
I don't see any issue. See below 2 options are
static void Main(string[] args)
{
string json = File.ReadAllText("json1.json");
JObject jObject = JObject.Parse(json);
var results = jObject["results"];
var payroll_report = results["payroll_report"];
var user314568 = payroll_report["314568"];
var total_pto_seconds = user314568["total_pto_seconds"];
var pto_seconds = user314568["pto_seconds"];
///**************option1***********************
var val1 = pto_seconds["22322828"];
var val2 = pto_seconds["12597955"];
Console.WriteLine($"22322828: {val1}");
Console.WriteLine($"22322828: {val2}");
///**************option2***********************
var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(pto_seconds.ToString());
foreach (var item in dict)
{
Console.WriteLine($"{item.Key}: {item.Value}");
}
Console.ReadLine();
}

How to compare two Json objects using C#

I have two Json objects as below need to be compared. I am using Newtonsoft libraries for Json parsing.
string InstanceExpected = jsonExpected;
string InstanceActual = jsonActual;
var InstanceObjExpected = JObject.Parse(InstanceExpected);
var InstanceObjActual = JObject.Parse(InstanceActual);
And I am using Fluent Assertions to compare it. But the problem is Fluent assertion fails only when the attribute count/names are not matching. If the json values are different it passes. I require to fail when values are different.
InstanceObjActual.Should().BeEquivalentTo(InstanceObjExpected);
For example I have the actual and expected json to compare as below. And using the above way of comparing make them Pass which is wrong.
{
"Name": "20181004164456",
"objectId": "4ea9b00b-d601-44af-a990-3034af18fdb1%>"
}
{
"Name": "AAAAAAAAAAAA",
"objectId": "4ea9b00b-d601-44af-a990-3034af18fdb1%>"
}
I did a bit more digging and was able to find out why the OP's test code doesn't run as expected. I was able to fix it by installing and using the FluentAssertions.Json nuget package.
One important thing:
Be sure to include using FluentAssertions.Json otherwise false
positives may occur.
Test code is the following:
using FluentAssertions;
using FluentAssertions.Json;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NUnit.Framework;
[TestFixture]
public class JsonTests
{
[Test]
public void JsonObject_ShouldBeEqualAsExpected()
{
JToken expected = JToken.Parse(#"{ ""Name"": ""20181004164456"", ""objectId"": ""4ea9b00b-d601-44af-a990-3034af18fdb1%>"" }");
JToken actual = JToken.Parse(#"{ ""Name"": ""AAAAAAAAAAAA"", ""objectId"": ""4ea9b00b-d601-44af-a990-3034af18fdb1%>"" }");
actual.Should().BeEquivalentTo(expected);
}
}
Running the test:
Consider using the JToken.DeepEquals() method provided by Newtonsoft. It would look somewhat like this, regardless of which testing framework you're using:
Console.WriteLine(JToken.DeepEquals(InstanceObjActual, InstanceObjExpected));
// false
Made a non-recursive method which will remove twins - idea is to remove same elements from very similar JSONs, so that there will remain only different nodes in each object:
public void RemoveTwins(ref BreadthFirst bf1, ref BreadthFirst bf2) {
JsonNode traversal = bf1.Next();
Boolean removed = false;
do {
if (!removed) {
if (bf2.Current != null) while (bf1.Level == bf2.Level && bf2.Next() != null) ;
if (bf2.Current != null) while (bf1.Level != bf2.Level && bf2.Next() != null) ;
else bf2.Current = bf2.root;
}
else traversal = bf1.Next();
if (bf2.Level < 0) bf2.Current = bf2.Root;
do {
removed = bf1.NextAs(bf1.src, bf2, bf2.src);
if (removed && bf1.Orphan && bf2.Orphan) {
JsonNode same = bf1.Current.Parent;
traversal = bf1.RemoveCurrent();
same = bf2.Current.Parent;
bf2.RemoveCurrent();
bf1.UpdateLevel();
bf2.UpdateLevel();
if (traversal == null
|| bf1.Root == null || bf2.Root == null
|| (bf1.Level == 0 && bf1.Current.NodeBelow == null)) {
traversal = null;
break;
}
} else
if (!removed) {
break;
} else removed = false;
} while (removed);
if (!removed) traversal = bf1.Next();
} while (traversal != null);
}
Complete code + parser on my GitHub (profile or below).
Older CSV version which also sorts input mentioned in my question here How to compare big JSON's? (new one does not, so it could be very slow when one of objects has reversed order - it would be easier to sort during parsing or at least compare both neighbours of twins as first search step)
One option is to deserialize the json strings into C# objects and compare them.
This approach requires more work comparing to using JToken.DeepEquals (as suggested by #JessedeWit), but has the advantage of giving better error messages if your tests fail (see screenshot below).
Your json string can be modelled into the following class:
public class Entity
{
[JsonProperty("Name")]
public string Name { get; set; }
[JsonProperty("objectId")]
public string ObjectId { get; set; }
}
In your test, deserialize the json strings into objects and compare them:
[TestFixture]
public class JsonTests
{
[Test]
public void JsonString_ShouldBeEqualAsExpected()
{
string jsonExpected = #"{ ""Name"": ""20181004164456"", ""objectId"": ""4ea9b00b-d601-44af-a990-3034af18fdb1%>"" }";
string jsonActual = #"{ ""Name"": ""AAAAAAAAAAAA"", ""objectId"": ""4ea9b00b-d601-44af-a990-3034af18fdb1%>"" }";
Entity expectedObject = JsonConvert.DeserializeObject<Entity>(jsonExpected);
Entity actualObject = JsonConvert.DeserializeObject<Entity>(jsonActual);
actualObject.Should().BeEquivalentTo(expectedObject);
}
}
PS: I used NUnit and FluentAssertions in my test method. Running the test:
After you deserialize the json to C# object the correct way is to implement the IComparable interface in the deserialized class and compare the 2 objects.
So:
using System;
using System.Collections.Generic;
class MyObj : IComparable<MyObj>
{
public string Name { get; set; }
public string ObjectID { get; set; }
public int CompareTo(MyObj other)
{
if ((this.Name.CompareTo(other.Name) == 0) &&
(this.ObjectID.CompareTo(other.ObjectID) == 0))
{
return 0;
}
return -1;
}
}
I needed two objects for Audit Logging and I wrote a code like below. It worked great for me.
https://github.com/wbish/jsondiffpatch.net
public static bool DeepCompare(this object obj, object another)
{
var diffObj = new JsonDiffPatch();
if (ReferenceEquals(obj, another)) return true;
if ((obj == null) || (another == null)) return false;
if (obj.GetType() != another.GetType()) return false;
var objJson = JsonConvert.SerializeObject(obj);
var anotherJson = JsonConvert.SerializeObject(another);
var result = diffObj.Diff(objJson, anotherJson);
return result == null;
}

How can I parse instance properties by using json data?

I try to parse json data to List<Employee> instance. But I don't want to use Json-to-C# tool for creating a shadow from json pattern. I want to take values only. Maybe I can use keys to take values (Employee). I want to fill a List of Employee.
My Json:
{
"type":"SUCCESS",
"msg":"Container RBFFiyatlama2_1.0.1 successfully called.",
"result":{
"execution-results":{
"results":[
{
"value":2,
"key":""
},
{
"value":{
"com.myteam.rbffiyatlama2.Employee":{
"salary":2400.0,
"age":35,
"cofactor":0.2
}
},
"key":"Employee0"
},
{
"value":{
"com.myteam.rbffiyatlama2.Employee":{
"salary":4800.0,
"age":35,
"cofactor":0.2
}
},
"key":"Employee1"
}
],
"facts":[
{
"value":{
"org.drools.core.common.DefaultFactHandle":{
"external-form":"0:88:1504512052:1504512052:160:DEFAULT:NON_TRAIT:com.myteam.rbffiyatlama2.Employee"
}
},
"key":"Employee0"
},
{
"value":{
"org.drools.core.common.DefaultFactHandle":{
"external-form":"0:89:213603577:213603577:159:DEFAULT:NON_TRAIT:com.myteam.rbffiyatlama2.Employee"
}
},
"key":"Employee1"
}
]
}
}
}
How can I fill Employee without creating any C# class by using above json.
public class Employee
{
public int age { get; set; }
public double cofactor { get; set; }
public int salary { get; set; }
}
You could use dynamics. The following should do what you're after and it's all native:
string jsonString = YourGetJsonStringMethod();
List<Employee> employees = new List<Employee>();
dynamic data = System.Web.Helpers.Json.Decode(jsonString);
dynamic results = data["result"]["execution-results"]["results"];
if (results.Length > 1)
{
for (var i = 1; i < results.Length; i++)
{
var dynamicEmployee = results[i]["value"]["com.myteam.rbffiyatlama2.Employee"];
dynamicEmployee["salary"] = (int) dynamicEmployee["salary"];
var encoded = System.Web.Helpers.Json.Encode(dynamicEmployee);
employees.Add(System.Web.Helpers.Json.Decode<Employee>(encoded));
}
}
You will obviously need to include System.Web.Helpers in your references, which you can find under Assemblies > Extensions in your Visual Studio Reference Manager.
Bear in mind that this code may raise an exception when you're debugging. If so, refer to this question for the solution.
This code "just works". I will leave it to you to do validation, null-checking and exception catching.

Parse JSON array in c# to read array collection inside json

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:

How to get values from a Jobject

I am using the Newtonsoft JSon c# plugin. I jave a JArray
{"data":[{"name":"Wesley 1","id":"616611941"},{"name":"Wesley 2","id":"100000138033375"},..............
I was wondering is there a way to loop though each object between the curly braces and extract the name and id of each entry?
Thanks to anyone who can help
According to some other questions you could try:
var array = JArray.Parse(json);
and then do a
foreach(var item in array)
// do something
dynamic dynObj = JsonConvert.DeserializeObject(json);
foreach (var item in dynObj.data)
{
Console.WriteLine("{0} {1}",item.name,item.id);
}
using jQuery you can do this. First loop will go thorough each item in array. second loop will get the key, value in each array item
$.each(data, function() {
$.each(this, function(key, value) {
//do what ever you want
});
});
EDIT
OK. You got some good answers from others. Here is another way.
namespace
using System.Web.Script.Serialization;
You add strongly typed class that maps data in the json
public class wordList
{
public List<NameId> data { get; set; }
public wordList()
{
data = new List<NameId>();
}
}
public class NameId
{
public string name { get; set; }
public string id { get; set; }
}
then you call
string jsonObj = #"{""data"":[{""name"":""Wesley 1"",""id"":""616611941""},{""name"":""Wesley 2"",""id"":""100000138033375""}]}";
JavaScriptSerializer jsSer = new JavaScriptSerializer();
wordList wl = jsSer.Deserialize<wordList>(jsonObj);
You can loop through the WordList to get the name, id values
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
List<JObject> data = JsonConvert.DeserializeObject<List<JObject>>(requestBody);
foreach(JObject d in data)
{
string name = d.GetValue("name").ToString();
string id = d.GetValue("id").ToString();
}

Categories