JsonPath for .NET( http://code.google.com/p/jsonpath/downloads/list )を使用しようとしていますが、解析方法の例を見つけるのに問題があります。 Json文字列とJsonPath文字列を使用して結果を取得します。
誰かがこれを使用しましたか?
発生している問題は、JsonPathのC#バージョンにJsonパーサーが含まれていないため、シリアル化と逆シリアル化を処理する別のJsonフレームワークで使用する必要があることです。
JsonPathが機能する方法は、IJsonPathValueSystem
と呼ばれるインターフェースを使用して、解析されたJsonオブジェクトをトラバースすることです。 JsonPathには、BasicValueSystem
インターフェースを使用してJsonオブジェクトを表し、IDictionary
インターフェースを使用してJson配列を表す組み込みのIList
が付属しています。
C#コレクション初期化子を使用してオブジェクトを構築することで独自のBasicValueSystem
互換のJsonオブジェクトを作成できますが、たとえば、Jsonがリモートサーバーから文字列の形式で提供される場合、これはあまり役に立ちません。
したがって、Json文字列を取得して、それをIDictionary
オブジェクト、IList
配列、およびプリミティブ値のネストされた構造に解析できる場合は、JsonPathを使用してフィルタリングできます。運が良ければ、優れたシリアル化および逆シリアル化機能を備えたJson.NETを使用して、ジョブのその部分を実行できます。
残念ながら、Json.NETはJson文字列をBasicValueSystem
と互換性のある形式に逆シリアル化しません。したがって、Json.NETでJsonPathを使用するための最初のタスクは、JsonNetValueSystem
を実装し、IJsonPathValueSystem
オブジェクト、JObject
配列、およびを理解するJArray
を作成することです。 JValue
はJObject.Parse
プロデュース。
したがって、JsonPathとJson.NETの両方をダウンロードして、C#プロジェクトに配置します。次に、このクラスをそのプロジェクトに追加します。
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;
}
}
これらのすべて3を使用して、サンプルの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();
}
}
これはこの出力を生成します:
["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]
この例は、JsonPathサイトのJavascriptサンプルに基づいています。
LINQ(.NET 2.0)が気に入らない場合:
namespace JsonPath
{
public sealed class JsonNetValueSystem : IJsonPathValueSystem
{
public bool HasMember(object value, string member)
{
if (value is Newtonsoft.Json.Linq.JObject)
{
// return (value as JObject).Properties().Any(property => property.Name == member);
foreach (Newtonsoft.Json.Linq.JProperty property in (value as Newtonsoft.Json.Linq.JObject).Properties())
{
if (property.Name == member)
return true;
}
return false;
}
if (value is Newtonsoft.Json.Linq.JArray)
{
int index = ParseInt(member, -1);
return index >= 0 && index < (value as Newtonsoft.Json.Linq.JArray).Count;
}
return false;
}
public object GetMemberValue(object value, string member)
{
if (value is Newtonsoft.Json.Linq.JObject)
{
var memberValue = (value as Newtonsoft.Json.Linq.JObject)[member];
return memberValue;
}
if (value is Newtonsoft.Json.Linq.JArray)
{
int index = ParseInt(member, -1);
return (value as Newtonsoft.Json.Linq.JArray)[index];
}
return null;
}
public System.Collections.IEnumerable GetMembers(object value)
{
System.Collections.Generic.List<string> ls = new System.Collections.Generic.List<string>();
var jobject = value as Newtonsoft.Json.Linq.JObject;
/// return jobject.Properties().Select(property => property.Name);
foreach (Newtonsoft.Json.Linq.JProperty property in jobject.Properties())
{
ls.Add(property.Name);
}
return ls;
}
public bool IsObject(object value)
{
return value is Newtonsoft.Json.Linq.JObject;
}
public bool IsArray(object value)
{
return value is Newtonsoft.Json.Linq.JArray;
}
public bool IsPrimitive(object value)
{
if (value == null)
throw new System.ArgumentNullException("value");
return value is Newtonsoft.Json.Linq.JObject || value is Newtonsoft.Json.Linq.JArray ? false : true;
}
private int ParseInt(string s, int defaultValue)
{
int result;
return int.TryParse(s, out result) ? result : defaultValue;
}
}
}
使用法:
object obj = Newtonsoft.Json.JsonConvert.DeserializeObject(input);
JsonPath.JsonPathContext context = new JsonPath.JsonPathContext { ValueSystem = new JsonPath.JsonNetValueSystem() };
foreach (JsonPath.JsonPathNode node in context.SelectNodes(obj, "$.store.book[*].author"))
{
Console.WriteLine(node.Value);
}