I want to create a method with the C# Newtonsoft library that can take in a parameter value to return the JSON data value, without needing to know and create a class beforehand, but all I can find are examples to deserialise into a class or into a dynamic object, both needing to know JSON structure prior at development time
Here's an example of what the kind of JSON format I'm expecting, but is subject to change:
{
"Input":
[
{
"Name": "foo"
},
{
"Name": "bar"
},
]
"Output":
[
{
"Name": "bob"
},
{
"Name": "builder"
},
]
}
I'm locked into using Newtonsoft library to work on the JSON file, or do it myself from scratch as it's an embedded system.
You can use JObject. If you deserialize a class without the type it will be deserialized to JObject. You would access your JObject values with named index which is obviously your property name. Other type of interest to you is JArray. This all resides in namespaces:
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
Example:
So the example with your JSON would be:
var json = #"{
""Input"":
[
{ ""Name"": ""foo"" },
{ ""Name"": ""bar"" }
],
""Output"":
[
{ ""Name"": ""bob"" },
{""Name"": ""builder""}
]
}";
var obj = JsonConvert.DeserializeObject(json) as JObject;
var input = obj["Input"] as JArray;
var inputArray = input[0]["Name"];
This would get the first element in array that is in Input field - "foo".
Related
How to get json object using path in string variable,This is the JSON Schema data structure string stored in my database,I tried to convert to json data structure but it didn't work,I want to convert such a string data structure into a json object.
string json = $#"{{
""xcollapse.id"":""xcollapse"",
""xcollapse.el"":202,
""xcollapse.cols.props.cn"":""title"",
""xcollapse.cols.props.desc"":"""",
""xcollapse.cols.props.visible"":-1,
""xcollapse.cols.children.id"":""f272681"",
""xcollapse.cols.children.el"":200,
""xcollapse.cols.children.props"":""{{}}""
}}";
var jObj = JObject.Parse(json);
var result = jObj.ToString();
I would like to get the following results.
{
"xcollapse": {
"id": "xcollapse",
"el": "202",
"cols": [
{
"props": {
"cn": "title",
"desc": "",
"visible": "-1"
},
"children": {
"id": "title",
"el": "",
"props": [
{}
]
}
}
]
}
}
The complete data structure in the database looks like this,I now need to convert to json objects to return to the front end.
{
"xcollapse.id":"xcollapse",
"xcollapse.el":202,
"xcollapse.props":{
},
"xcollapse.styles.visible":-1,
"xcollapse.cols.deletable":false,
"xcollapse.cols.props.cn":"title",
"xcollapse.cols.props.desc":"",
"xcollapse.cols.props.visible":-1,
"xcollapse.cols.styles":null,
"xcollapse.cols.children.id":"f272681",
"xcollapse.cols.children.el":200,
"xcollapse.cols.children.props":{
},
"xcollapse.cols.children.styles.visible":-1,
"xcollapse.cols.children.cols.deletable":false,
"xcollapse.cols.children.cols.props.visible":-1,
"xcollapse.cols.children.cols.styles.span":8,
"xcollapse.cols.children.cols.children.id":"fname",
"xcollapse.cols.children.cols.children.el":100,
"xcollapse.cols.children.cols.children.props.ek":"fbillhead",
"xcollapse.cols.children.cols.children.props.cn":"title",
"xcollapse.cols.children.cols.children.props.group":"",
"xcollapse.cols.children.cols.children.props.fn":"fname",
"xcollapse.cols.children.cols.children.props.pn":"fname",
"xcollapse.cols.children.cols.children.props.desc":"",
"xcollapse.cols.children.cols.children.props.must":"0",
"xcollapse.cols.children.cols.children.props.visible":-1,
"xcollapse.cols.children.cols.children.props.len":"100",
"xcollapse.cols.children.cols.children.props.lock":"0",
"xcollapse.cols.children.cols.children.props.copy":"1",
"xcollapse.cols.children.cols.children.props.defval":"",
"xcollapse.cols.children.cols.children.props.canchange":"0",
"xcollapse.cols.children.cols.children.props.xlsin":"1",
"xcollapse.cols.children.cols.children.props.acl":"1",
"xcollapse.cols.children.cols.children.props.sbm":"0",
"xcollapse.cols.children.cols.children.props.notrace":"1",
"xcollapse.cols.children.cols.children.props.apipn":"sourceType",
"xcollapse.cols.children.cols.children.props.ctlfk":"",
"xcollapse.cols.children.cols.children.props.editmode":"0",
"xcollapse.cols.children.cols.children.props.xsslv":"0",
"xcollapse.cols.children.cols.children.styles.align":"left",
"xcollapse.cols.children.cols.children.styles.width":"",
"xcollapse.cols.children.cols.children.styles.row":2,
"xcollapse.cols.children.cols.children.cols":{},
"xcollapse.cols.children.cols.children.deletable":true,
"xcollapse.cols.children.cols.children.pid":"",
"xcollapse.cols.children.cols.children.seq":1,
"xcollapse.cols.children.cols.seq":1,
"xcollapse.cols.children.deletable":true,
"xcollapse.cols.children.pid":"",
"xcollapse.cols.children.seq":1,
"xcollapse.cols.seq":1,
"xcollapse.deletable":true,
"xcollapse.pid":"",
"xcollapse.seq":1,
}
How can i acces the first item id?
using (var http = new HttpClient())
{
var res = JArray.Parse(await http.GetStringAsync("http://api.champion.gg/champion/Gragas?api_key=????").ConfigureAwait(false));
^^^^^^ // Also tried with JObject instead of JArray, both don't work
var champion = (Uri.EscapeUriString(res[0]["items"][0]["mostGames"][0]["items"][0]["id"].ToString()));
Console.WriteLine(champion); // ^ [0] here because the JSON starts with an [
}
Example JSON result (made it smaller because the original JSON is over 21500 characters, made sure its valid with https://jsonlint.com, here is the original JSON response: https://hastebin.com/sacikozano.json)
[{
"key": "Gragas",
"role": "Jungle",
"overallPosition": {
"change": 1,
"position": 13
},
"items": {
"mostGames": {
"items": [{
"id": 1402,
"name": "Enchantment: Runic Echoes"
},
{
"id": 3158,
"name": "Ionian Boots of Lucidity"
},
{
"id": 3025,
"name": "Iceborn Gauntlet"
},
{
"id": 3065,
"name": "Spirit Visage"
},
{
"id": 3742,
"name": "Dead Man's Plate"
},
{
"id": 3026,
"name": "Guardian Angel"
}
],
"winPercent": 50.45,
"games": 300
}
}
}]
With JArray i get the following error: Accessed JObject values with invalid key value: 0. Object property name expected.
With JObject i get the following error: Error reading JObject from JsonReader. Current JsonReader item is not an object: StartArray. Path '', line 1, position 1.
Thanks in advance, i hope i explained it well
It should be:
var champion = (Uri.EscapeUriString(res[0]["items"]["mostGames"]["items"][0]["id"].ToString()));
The outermost "items" property has a single object as its value, not an array, so [0] is not needed in ["items"][0]. Similarly "mostGames" has a single object value so the [0] is not needed in ["mostGames"][0].
Sample fiddle.
Note that if "items" is sometimes an array of objects, but sometimes is a single object instead of an array of one object, you can introduce the following extension method:
public static class JsonExtensions
{
public static IEnumerable<JToken> AsArray(this JToken item)
{
if (item is JArray)
return (JArray)item;
return new[] { item };
}
}
And do:
var champion = (Uri.EscapeUriString(res[0]["items"].AsArray().First()["mostGames"]["items"][0]["id"].ToString()));
I have a requirement to get the first set of records in c# JSON. Here is my JSON data for example
string sJSON = "{
{
"ID": "1",
"Name":"John",
"Area": "Java" ,
"ID": "2",
"Name": "Matt",
"Area": "Oracle" ,
"ID": "3","Name":
"Danny","Area": "Android"
}
}"
I need to extract only the 1st set of records (i.e. {{"ID": "1", "Name":"John", "Area": "Java"}}).
If there is only one record my code (see below) works fine but when there are multiple records it takes the last set of JSON data (i.e. {{"ID": "3","Name": "Danny","Area": "Android"}}).
JObject jsonObject = JObject.Parse(sJSON);
string sID = (string)jsonObject["ID"];
string sName = (string)jsonObject["Name"];
string sArea = (string)jsonObject["Area"];
Can anyone help me extract only the 1st set of JSON data?
You return the JSON data as JSON Array, now it is a simple JSON string.
If you're able to generate like below then you can easily get the single JSON element easily.
[{ "ID": "1", "Name":"John", "Area": "Java" },{ "ID": "2","Name": "Matt","Area": "Oracle" },{ "ID": "3","Name": "Danny","Area": "Android" } ]
Use the below link, to understand this JSON format.
http://json.parser.online.fr/
Parse the data as JToken.
Such that you have something like:
var jToken = JToken.Parse(sJSON);
var isEnumerable = jToken.IsEnumerable()
if(isEnumeable)
{
cast as JArray and get firstOrdefault
}
var isObject = jToken.IsObject();
if(isObject )
{
cast as JObject and perform straight casting
}
I have a little utility where we extract values from JSON using JObject.SelectToken(path). We need to determine the paths at run-time. Works perfectly.
What I now need to do is to write back into the JSON (JObject or other) using the same path string. I've hunted and searched and I can't quite find if there is anything that does this quite as cleanly as SelectToken does for reading.
(I'm also stuck in 3.5 CF)
For example, something like:
... JObject read in already ...
var theJToken = theJObject.SelectToken("animals.cat[3].name");
theTJoken.SetValue("Bob"); // Of course this doesn't exist
... serialize it ...
JToken.SelectToken actually returns a JToken which can be modified using JToken.Replace. You can use that to replace the node within your JSON object, mutating the original object.
JObject o = JObject.Parse(#"{ 'cats': [
{ 'name': 'cat 1' },
{ 'name': 'cat 2' },
{ 'name': 'cat 3' } ] }");
// get the token
JToken secondCatName = o.SelectToken("cats[1].name");
// replace the name
secondCatName.Replace("meow");
// and the original object has changed
Console.WriteLine(o.ToString());
// { "cats": [ { "name": "cat 1" }, { "name": "meow" }, { "name": "cat 3" } ] }
This is the JSON I get from a request on .NET:
{
"id": "110355660738",
"picture": {
"data": {
"url": "https://fbcdn-profile-a.akamaihd.net/hprofile-ak-prn2/1027085_12033235063_5234302342947_n.jpg",
"is_silhouette": false
}
}
}
and I'd like to catch the field "url", using (maybe?) LINQ. I do many request as this, that differents a bit. So I won't to create a C# Class and deserialize it every time.
Is it a way to extract a single field? Thank you!
No need for Linq, just use dynamic (using Json.Net)
dynamic obj = JObject.Parse(json);
Console.WriteLine((string)obj.picture.data.url);
Linq version would not be much readable
JObject jObj = JObject.Parse(json);
var url = (string)jObj.Descendants()
.OfType<JProperty>()
.Where(p => p.Name == "url")
.First()
.Value;
Documentation: LINQ to JSON
I would not recommend LINQ. I would recommend a JSON library such as newtonsoft.json.
So you can do this:
string json = #"{
""Name"": ""Apple"",
""Expiry"": "2008-12-28T00:00:00",
""Price"": 3.99,
""Sizes"": [
""Small"",
""Medium"",
""Large""
]
}";
JObject o = JObject.Parse(json);
string name = (string)o["Name"];
// Apple
JArray sizes = (JArray)o["Sizes"];
string smallest = (string)sizes[0];
// Small
Note:- this code has been copied from the samples present on the project site
http://james.newtonking.com/pages/json-net.aspx
In a bind you could always deserialize the JSON and serialize it to XML, and load the XML in a XDocument. Then you can use the classic Linq to XML. When you are done take the XML, deserialize it, and serialize it back to JSON to JSON. We used this technique to add JSON support to an application that was originally built for XML, it allowed near-zero modifications to get up and running.
You can easily query with LINQ like this
considering this JSON
{
"items": [
{
"id": "10",
"name": "one"
},
{
"id": "12",
"name": "two"
}
]
}
let's put it in a variable called json like this,
JObject json = JObject.Parse("{'items':[{'id':'10','name':'one'},{'id':'12','name':'two'}]}");
you can select all ids from the items where name is "one" using the following LINQ query
var Ids =
from item in json["items"]
where (string)item["name"] == "one"
select item["id"];
Then, you will have the result in an IEnumerable list