【问题标题】:How to use C# example using JsonPath?如何使用 JsonPath 使用 C# 示例?
【发布时间】:2011-11-24 03:25:38
【问题描述】:

我正在尝试将 JsonPath 用于 .NET (http://code.google.com/p/jsonpath/downloads/list),但我无法找到如何解析 Json 字符串和 JsonPath 字符串并获得结果的示例。

有人用过吗?

【问题讨论】:

标签: c# jsonpath


【解决方案1】:

我发现只要不需要过滤,内部的 JavaScriptSerializer() 就可以正常工作。

使用来自JsonPath Dataset + Examples的数据集和示例

我的 JsonPath 实现来源是 GitHub

public static string SelectFromJson(string inputJsonData, string inputJsonPath)
{
    // Use the serializer to deserialize the JSON but also to create the snippets
    var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
    serializer.MaxJsonLength = Int32.MaxValue;

    dynamic dynJson = serializer.Deserialize<object>(inputJsonData);

    var jsonPath = new JsonPath.JsonPathContext();
    var jsonResults = jsonPath.Select(dynJson, inputJsonPath);

    var valueList = new List<string>();
    foreach (var node in jsonResults)
    {
        if (node is string)
        {
            valueList.Add(node);
        }
        else
        {
            // If the object is too complex then return a list of JSON snippets
            valueList.Add(serializer.Serialize(node));
        }
    }
    return String.Join("\n", valueList);
}

函数使用如下。

    var result = SelectFromJson(@"
{ ""store"": {
        ""book"": [ 
            { ""category"": ""fiction"",
                ""author"": ""J. R. R. Tolkien"",
                ""title"": ""The Lord of the Rings"",
                ""isbn"": ""0-395-19395-8"",
                ""price"": 22.99
            }
        ]
    }
}", "$.store.book[*].author");

【讨论】:

    【解决方案2】:

    使用 Newtonsoft.Json.Linq 哟可以使用函数 SelectToken 并尝试你的 JsonPath 查看文档https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Linq_JObject.htm

    Object jsonObj = JObject.Parse(stringResult);
    
    JToken pathResult = jsonObj.SelectToken("results[0].example");
    
    return pathResult.ToString();
    

    【讨论】:

      【解决方案3】:

      对于那些不喜欢 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);
      }
      

      【讨论】:

        【解决方案4】:

        您遇到的问题是 C# 版本的 JsonPath 不包含 Json 解析器,因此您必须将它与另一个处理序列化和反序列化的 Json 框架一起使用。

        JsonPath 的工作方式是使用一个名为IJsonPathValueSystem 的接口来遍历解析后的Json 对象。 JsonPath 自带了一个内置的BasicValueSystem,使用IDictionary 接口表示Json 对象,使用IList 接口表示Json 数组。

        您可以通过使用 C# 集合初始化器构造它们来创建自己的 BasicValueSystem 兼容的 Json 对象,但是当您的 Json 以字符串形式从远程服务器传入时,这并没有多大用处。

        因此,如果您可以获取一个 Json 字符串并将其解析为 IDictionary 对象、IList 数组和原始值的嵌套结构,那么您就可以使用 JsonPath 对其进行过滤!幸运的是,我们可以使用具有良好序列化和反序列化功能的 Json.NET 来完成这部分工作。

        不幸的是,Json.NET 不会将 Json 字符串反序列化为与 BasicValueSystem 兼容的格式。因此,在 Json.NET 中使用 JsonPath 的首要任务是编写一个实现 IJsonPathValueSystem 并理解 JObject 对象、JArray 数组和 JValue 值的 JsonNetValueSystem 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;
            }
        }
        

        现在有了所有三个,我们可以编写一个示例 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 示例:

        【讨论】:

        • 与其编写大量代码并使用两个库,不如像这样使用 Json.Net 更容易: JObject json = JObject.Parse(@input); var values = json.SelectToken("store.book").Values("author");
        • 这个答案回答了这个问题。当然,根据要解决的问题,还有许多其他方法。
        • 谢谢!正是我需要的。 Json.Net 的 SelectToken 没有我需要的功能。
        • 精心制作的答案,谢谢!正是我想要的。
        • 嗨 Rick,我正在尝试使用 JsonPath 中的表达式作为示例,似乎为了支持我必须实现 JsonPathScriptEvaluator,就像您实现了 IJsonPathValueSystem 一样。你有相同的示例实现吗?我还发布了一个单独的问题stackoverflow.com/questions/16566359/…
        猜你喜欢
        • 2022-01-02
        • 2021-05-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-30
        • 2019-01-08
        • 1970-01-01
        • 2015-08-28
        相关资源
        最近更新 更多