Il problema che si verifica è che la versione C# di JsonPath non include un parser Json, quindi è necessario utilizzarlo con un altro framework Json che gestisca la serializzazione e la deserializzazione.
Il modo in cui funziona JsonPath consiste nell'utilizzare un'interfaccia denominata IJsonPathValueSystem
per attraversare oggetti JSON analizzati. JsonPath viene fornito con un BasicValueSystem
integrato che utilizza l'interfaccia IDictionary
per rappresentare gli oggetti Json e l'interfaccia IList
per rappresentare gli array JSON.
È possibile creare i propri oggetti JSON compatibili con BasicValueSystem
costruendoli utilizzando gli inizializzatori di raccolta C#, ma questo non è di grande utilità quando ad esempio il JSON arriva sotto forma di stringhe da un server remoto.
Quindi, se solo si potesse prendere una stringa Json e analizzarla in una struttura annidata di oggetti IDictionary
, IList
e valori primitivi, si potrebbe quindi utilizzare JsonPath per filtrarlo! Per fortuna, possiamo usare Json.NET che ha buone capacità di serializzazione e deserializzazione per fare quella parte del lavoro.
Sfortunatamente, Json.NET non deserializza le stringhe di Json in un formato compatibile con lo BasicValueSystem
. Quindi il primo compito per l'utilizzo di JsonPath con Json.NET è scrivere un JsonNetValueSystem
che implementa IJsonPathValueSystem
e che comprenda gli oggetti JObject
, gli array JArray
e i valori JValue
prodotti da JObject.Parse
.
Quindi scaricare sia JsonPath che Json.NET e inserirli in un progetto C#. Quindi aggiungere questa classe per quel progetto:
public sealed class JsonNetValueSystem : IJsonPathValueSystem
{
public bool HasMember(object value, string member)
{
if (value is JObject)
return (value as JObject).Properties().Any(property => property.Name == member);
if (value is JArray)
{
int index = ParseInt(member, -1);
return index >= 0 && index < (value as JArray).Count;
}
return false;
}
public object GetMemberValue(object value, string member)
{
if (value is JObject)
{
var memberValue = (value as JObject)[member];
return memberValue;
}
if (value is JArray)
{
int index = ParseInt(member, -1);
return (value as JArray)[index];
}
return null;
}
public IEnumerable GetMembers(object value)
{
var jobject = value as JObject;
return jobject.Properties().Select(property => property.Name);
}
public bool IsObject(object value)
{
return value is JObject;
}
public bool IsArray(object value)
{
return value is JArray;
}
public bool IsPrimitive(object value)
{
if (value == null)
throw new ArgumentNullException("value");
return value is JObject || value is JArray ? false : true;
}
private int ParseInt(string s, int defaultValue)
{
int result;
return int.TryParse(s, out result) ? result : defaultValue;
}
}
Ora con tutte e tre di questi pezzi possiamo scrivere un programma di esempio JsonPath:
class Program
{
static void Main(string[] args)
{
var input = @"
{ ""store"": {
""book"": [
{ ""category"": ""reference"",
""author"": ""Nigel Rees"",
""title"": ""Sayings of the Century"",
""price"": 8.95
},
{ ""category"": ""fiction"",
""author"": ""Evelyn Waugh"",
""title"": ""Sword of Honour"",
""price"": 12.99
},
{ ""category"": ""fiction"",
""author"": ""Herman Melville"",
""title"": ""Moby Dick"",
""isbn"": ""0-553-21311-3"",
""price"": 8.99
},
{ ""category"": ""fiction"",
""author"": ""J. R. R. Tolkien"",
""title"": ""The Lord of the Rings"",
""isbn"": ""0-395-19395-8"",
""price"": 22.99
}
],
""bicycle"": {
""color"": ""red"",
""price"": 19.95
}
}
}
";
var json = JObject.Parse(input);
var context = new JsonPathContext { ValueSystem = new JsonNetValueSystem() };
var values = context.SelectNodes(json, "$.store.book[*].author").Select(node => node.Value);
Console.WriteLine(JsonConvert.SerializeObject(values));
Console.ReadKey();
}
}
che produce questo output:
["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]
Questo esempio è basato sull'esempio Javascript nel sito JsonPath:
potrei suggerire Json.NET come JSON alternativa parser (http://james.newtonking.com/pages/json-net.aspx) –
Ha una funzionalità simile a JsonPath? –
Qualcosa di simile a XPath? Lo fa. Controlla la funzionalità SelectToken di JSON.NET. È possibile utilizzare un'espressione stringa per ottenere JSON. Ad esempio: http: // StackOverflow.it/questions/1698175/what-is-the-json-net-equivilant-of-xmls-xpath-selectnodes-selectsinglenode –