C# 在C中使用带JsonPath的过滤器#

C# 在C中使用带JsonPath的过滤器#,c#,json.net,jsonpath,C#,Json.net,Jsonpath,我正在使用来查询一些JSON数据。JsonPath没有自带解析器,因此根据,我使用它将Json字符串解析为嵌套的IDictionary对象、IList数组和原语的集合。然后我使用JsonPath对其进行过滤(在添加中建议的类之后) 作为参考,以下是我的代码中实际处理所有这些问题的部分: // string exampleJsonString defined below string query = "$.store.book[*].title" // we should get a list o

我正在使用来查询一些JSON数据。JsonPath没有自带解析器,因此根据,我使用它将Json字符串解析为嵌套的
IDictionary
对象、
IList
数组和原语的集合。然后我使用JsonPath对其进行过滤(在添加中建议的类之后)

作为参考,以下是我的代码中实际处理所有这些问题的部分:

// string exampleJsonString defined below
string query = "$.store.book[*].title" // we should get a list of all titles

// step 1: use Json.NET to parse the json string into a JObject
JObject parsedJson = JObject.Parse(exampleJsonString); 

// step 2: use JsonPath with a custom ValueSystem (JsonNetValueSystem)
JsonPathContext context = new JsonPathContext    
        { ValueSystem = new JsonNetValueSystem() }; 

// step 3: get results using JsonPath
List<object> toRet = context.SelectNodes(parsedJson,
        query).Select(node => node.Value).ToList();

在查询中使用脚本表达式时(在
?(…)
部分),需要提供一个
ScriptEvaluator
方法来计算脚本。不幸的是,它们没有为C版本提供默认实现。您需要提供该实现

开箱即用,这不是最需要解决的问题,您需要编写一个解释器。您有两种选择:使用CodeDOM以C#代码(或您喜欢的任何语言)的形式编译和执行脚本,使用Roslyn解析脚本并进行计算,任何可行的方法都可以

对于这种特殊情况,一个快速而肮脏的解决方案是在脚本计算器方法中执行类似的操作:

object EvaluateScript(string script, object value, string context)
{
    if (script == "@.category == 'fiction'")
    {
        var obj = value as JObject;
        return (string)obj["category"] == "fiction";
    }
    return null;
}
下面是另一个利用IronPython评估脚本的解决方案

public class IronPythonScriptEvaluator
{
    private Lazy<ScriptEngine> engine = new Lazy<ScriptEngine>(() => Python.CreateEngine());
    private ScriptEngine Engine { get { return engine.Value; } }

    private const string ItemName = "_IronPythonScriptEvaluator_item";

    public object EvaluateScript(string script, object value, string context)
    {
        var cleanScript = CleanupScript(script);
        var scope = Engine.CreateScope();
        scope.SetVariable(ItemName, value);
        return Engine.Execute<bool>(cleanScript, scope);
    }

    private string CleanupScript(string script)
    {
        return Regex.Replace(script, @"@", ItemName);
    }
}
公共类IronPythonScriptEvaluator
{
private Lazy engine=new Lazy(()=>Python.CreateEngine());
私有脚本引擎引擎{get{return Engine.Value;}}
private const string ItemName=“\u IronPythonScriptEvaluator\u item”;
公共对象EvaluateScript(字符串脚本、对象值、字符串上下文)
{
var cleanScript=CleanupScript(脚本);
var scope=Engine.CreateScope();
scope.SetVariable(ItemName,value);
返回引擎.Execute(cleanScript,scope);
}
私有字符串清除脚本(字符串脚本)
{
返回Regex.Replace(脚本@“@”,ItemName);
}
}

另一个解决方案是使用。它具有内置的本机JSONPath实现和解析器(以及模式和序列化程序)。此外,不需要将路径表示为字符串。Json有一个流畅的接口,可以用来构建路径,包括表达式支持

要表示
$.store.book[*].title
,您需要

var path = JsonPathWith.Name("store")
                       .Name("book")
                       .Array()
                       .Name("title");
对于您的示例
$.store.book[?(@.category=='fiction')].title
,您可以使用

var path = JsonPathWith.Name("store")
                       .Name("book")
                       .Array(jv => jv.Name("category") == "fiction")
                       .Name("title");
更重要的是,这些表达式中对字段的支持也很有限


如果路径源是字符串,那么Manatee.Json也会处理路径解析

您是否尝试将JSON解析为类对象并使用Linq进行过滤?问题是,我事先不知道JSON的结构是什么。比如说,我不能用类别、作者、标题和价格设置Book类,因为该代码用于各种各样的数据库,其中大多数数据库都没有Book对象。所以我每次都要解析一个字符串到一个新的JObject。我不知道如何为每个新数据库创建自定义的类。有吗?如果是这样,那就太棒了。如果没有,据我所知,我认为我仍然坚持我所拥有的。我不太了解林克,所以如果有办法的话,那就太好了。我仍在试图弄清楚Linq自己。但JSON.Net似乎可以(通过一些工作)提供您想要的东西。我建议从这里查看文档:可能需要您点击JArray和IOObject方法,以获得所需的位置。啊哈,这看起来是我必须要做的。谢谢你为我指明了正确的方向。:)当我完成后,我会发布我所拥有的。如果您可以访问诸如IronPython之类的动态语言,您可以使用它来评估您的脚本。我已经包括了一个如何使用它的示例。这个
脚本评估器的文档在哪里?@theodler:据我所知,没有任何关于C#实现(或网站上提供的任何其他PHP实现)的文档。您必须查看源代码以了解它需要什么以及它试图做什么。它不是最复杂的代码,所以应该非常简单。
var path = JsonPathWith.Name("store")
                       .Name("book")
                       .Array(jv => jv.Name("category") == "fiction")
                       .Name("title");