Json.net how to use jsonpath with "$." - c#

I'm trying to use json.net from json as follows:
String JSONString =
#"[
{
""category"": ""reference"",
""author"": ""Nigel Rees"",
""title"": ""Sayings of the Century"",
""price"": 8.95
},
{
""category"": ""fiction"",
""author"": ""Still Here"",
""title"": ""Test remove title"",
""price"": 12.99,
""isbn"": ""0-553-21311-3""
}
]";
JObject JSONObject;
JSONObject = JObject.Parse(JSONString);
String JSONPath = #"$[0].title";
JSONObject.SelectToken(JSONPath);
Getting Exception:
ST.Acxiom.Test.DataJSONTest.DataJSONClass.GetToken: Newtonsoft.Json.JsonException : Property '$' does not exist on JObject.
What I'm doing wrong, even though I'm using valid jsonpath but still
getting error.
Is "$." not supported?
How to access Array item in
json in above example?
Any help would be appreciated.

Using JObject.Parse from your example throws JsonReaderException with the latest Json.net version. You have to use either JToken.Parse or JsonConvert.DeserializeObject.
SelectToken is intended to select child nodes so $ is not supported. You can access array item like this:
var jArray = JToken.Parse(JSONString); //It's actually a JArray, not a JObject
var jTitle = jArray.SelectToken("[0].title");
var title = (string)jTitle;

Related

how to add an empty array to a json payload?

Is it possible to add an array to a json payload?
For example, let's say this is my payload:
string json = #"{
'channel': {
'title': 'Star Wars',
'link': 'http://www.starwars.com',
'description': 'Star Wars blog.',
'obsolete': [{'something':'awesome'},{'a':'b'}],
'item': [],
'nested':[{'upgrademe':'please'}, {'upgrademe':'no'}]
}
}";
The result I'd like would be something like this:
string json = #"{
'channel': {
'title': 'Star Wars',
'link': 'http://www.starwars.com',
'description': 'Star Wars blog.',
'obsolete': [{'something':'awesome'},{'a':'b'}],
'item': [],
'nested':[{'upgrademe':'please', 'emptyArray':[]}, {'upgrademe':'no'}]
}
}";
For every channel.nested where upgrademe == please then I'd like to add an empty array like [].
before:
'nested':[{'upgrademe':'please'}, {'upgrademe':'no'}]
after:
'nested':[{'upgrademe':'please', 'emptyArray':[]}, {'upgrademe':'no'}]
My current implementation:
public static JObject AddArray(this JObject jObject, string path, string key, string value)
{
var obs = jObject.SelectToken(path);
if (obs == null)
{
return jObject;
}
foreach (var jsonObject in obs)
{
if (jsonObject.SelectToken(key).ToString().ToLower() != value.ToLower())
{
continue;
}
jObject.SelectToken(path).Parent.AddAfterSelf(new JValue(new JProperty("emptyArray", new JArray())));
}
return jObject;
}
I'm getting an exception on this line:
usage example:
var result = jobject.AddArray("channel.nested", "upgrademe", "please");
the above says the following:
find the object "channel.nested" and when upgrademe==please, add a sibbling node as an empty array
How do we conditionally add an array object to a json payload?
Since you're adding a new property into an object. You don't need to use JValue
Just use JProperty directly:
AddAfterSelf(new JProperty("emptyArray", new JArray()))

JSON.net - Write into JSON / JObject using path string

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" } ] }

Can I LINQ a JSON?

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

Deserialize json with Json.NET

I have JSON that looks like this (from the Philips HUE API):
{
"1": {"name": "Bedroom"},
"2": {"name": "Kitchen"}
}
When I try to deserialize this document I run into problems because the document is structured the way it is.
If it had been formated like this:
[
{"nr": "1", "name": "Bedroom"},
{"nr": "2", "name": "Kitchen"}
]
Everything would have been fine. Now I am forced to do string parsing in order to extract the data... :-(
Any ideas or suggestions?
I would deserialize to JObject and use it as Dictionary
var jObj = (JObject)JsonConvert.DeserializeObject(json);
Console.WriteLine(jObj["1"]["name"]);
or
dynamic jObj = JsonConvert.DeserializeObject(json);
Console.WriteLine(jObj["1"].name);

Generate JSON object with NewtonSoft in a single line

I'm using the JSON library NewtonSoft to generate a JSON string:
JObject out = JObject.FromObject(new
{
typ = "photos"
});
return out.ToString();
Output:
{
"typ": "photos"
}
My question:
Is it possible to get the output in a single line like:
{"typ": "photos"}
You can use the overload of JObject.ToString() which takes Formatting as parameter:
JObject obj = JObject.FromObject(new
{
typ = "photos"
});
return obj.ToString(Formatting.None);
var json = JsonConvert.SerializeObject(new { typ = "photos" }, Formatting.None);
Here's a one-liner to minify JSON that you only have a string for:
var myJson = "{\"type\" :\"photos\" }";
JObject.Parse(myJson).ToString(Newtonsoft.Json.Formatting.None)
Output:
{"type":"photos"}
I'm not sure if this is what you mean, but what I do is this::
string postData = "{\"typ\":\"photos\"}";
EDIT:
After searching I found this on Json.Net:
string json = #"{
CPU: 'Intel',
Drives: [
'DVD read/writer',
'500 gigabyte hard drive'
]
}";
JObject o = JObject.Parse(json);
and maybe you could use the info on this website.
But I'm not sure, if the output will be on one line... Good luck!
If someone here who doesn't want to use any external library in MVC, they can use the inbuilt System.Web.Script.Serialization.JavaScriptSerializer
One liner for that will be:
var JsonString = new JavaScriptSerializer().Serialize(new { typ = "photos" });

Categories

Resources