展平 JToken

2023-12-20

假设我有以下 JToken:

@"{
    ""data"": [
        {
            ""company"": {
                ""ID"": ""12345"",
                ""location"": ""Some Location""
            },
            ""name"": ""Some Name""
        }
    ]
}";

我想将此令牌传递到输出此 JToken 的 FlattenToken 函数中:

@"{
    ""data"": [
        {
            ""company_ID"": ""12345"",
            ""company_location"": ""Some Location"",
            ""name"": ""Some Name""
        }
]}"

这样做的原因是这样我就可以获取扁平化的 JToken 并将其反序列化到 DataTable 中。

不过,我在 JObject、JToken、JProperties 和其他 JMadness 的混乱中迷失了方向。我看到了答案这个帖子 https://stackoverflow.com/questions/15413825/how-do-you-add-a-jtoken-to-an-jobject,这很有帮助,但我仍然没有得到正确的结果。

这是我到目前为止所拥有的:

public static JToken FlattenToken(JToken token)
{
    foreach (JToken topLevelItem in token["data"].Children())
    {
        foreach (JToken field in topLevelItem.Value<JToken>())
        {
            foreach (JProperty property in field.Value<JObject>().Properties())
            {
                field.AddAfterSelf(JObject.Parse(@"{""" + property.Name + "_" + property.Value));
            }

            field.Remove();
        }
    }

    return token;
}

通过外部 foreach 循环的第一次迭代,topLevelItem =

{
    "company": {
        "ID": "12345"
    },
    "name": "Some Name"
}

通过第二个 foreach 循环的第一次迭代,field =

"company": {
    "ID": "12345"
}

到目前为止看起来不错。但是当我进入最里面的 foreach 循环时,我在 foreach 行上遇到异常:“无法将 Newtonsoft.Json.Linq.JProperty 转换为 Newtonsoft.Json.Linq.JToken。”

不知道那里发生了什么。我的印象是 field.Value 调用将生成一个 JToken 并尝试将其转换为 JProperty。那么,如错误所示,JProperty 在哪里尝试转换为 JToken?

而且,这感觉像是一种非常粗暴的扁平化 JToken 的方式。有没有更好的办法?


Json.NET 中对象的层次结构可能相当深。可以在以下位置找到粗略指南:这个答案 https://stackoverflow.com/questions/20532567/json-net-confusion-in-getting-parent-from-jtoken/20532778#20532778.

要解决您的问题,您首先需要一个扩展方法来获取 a 的属性JObject然后返回带有名称前缀的集合:

public static class JsonExtensions
{
    public static IEnumerable<KeyValuePair<string, JToken>> FlattenFields(this JObject obj, string prefix)
    {
        foreach (var field in obj)
        {
            string fieldName = prefix + "_" + field.Key;
            var fieldValue = field.Value;
            yield return new KeyValuePair<string, JToken>(fieldName, fieldValue);
        }
    }
}

接下来,您需要一些递归工具来迭代 Json.NET 层次结构并重写所选属性的集合JObject's:

public static class JsonExtensions
{
    public static IEnumerable<T> Yield<T>(this T item)
    {
        yield return item;
    }

    public static JToken EditFields(this JToken token, Func<KeyValuePair<string, JToken>, IEnumerable<KeyValuePair<string, JToken>>> editor)
    {
        if (token == null)
            return null;
        switch (token.Type)
        {
            case JTokenType.Array:
                return EditFields((JArray)token, editor);
            case JTokenType.Object:
                return EditFields((JObject)token, editor);
            default:
                return token;
        }
    }

    static JToken EditFields(JArray array, Func<KeyValuePair<string, JToken>, IEnumerable<KeyValuePair<string, JToken>>> editor)
    {
        JArray newArray = null;
        foreach (var element in array)
        {
            var newElement = EditFields(element, editor);
            if (newElement != null)
            {
                if (newArray == null)
                    newArray = new JArray();
                newArray.Add(newElement);
            }
        }
        return newArray;
    }

    static JToken EditFields(JObject obj, Func<KeyValuePair<string, JToken>, IEnumerable<KeyValuePair<string, JToken>>> editor)
    {
        JObject newObj = null;

        foreach (var field in obj)
        {
            foreach (var newField in editor(field))
            {
                if (newObj == null)
                    newObj = new JObject();
                newObj[newField.Key] = newField.Value.EditFields(editor);
            }
        }

        return newObj;
    }
}

最后,将它们放在一起创建一个方法来提升命名的属性JObject其父母的财产JObject,在属性名称前面加上下划线:

public static class JsonExtensions
{
    public static JToken PromoteNamedPropertiesToParents(this JToken token, string propertyName)
    {
        return token.EditFields(pair =>
        {
            if (pair.Key == propertyName && pair.Value is JObject)
            {
                return ((JObject)pair.Value).FlattenFields(pair.Key);
            }
            return pair.Yield();
        });
    }
}

然后,进行测试:

public static class TestFlatten
{
    public static void Test()
    {
        string jsonString = @"{
            ""data"": [
                {
                    ""company"": {
                        ""ID"": ""12345"",
                        ""location"": ""Some Location""
                    },
                    ""name"": ""Some Name""
                }
            ]
        }";
        JObject obj = JObject.Parse(jsonString);
        var newObj = (JObject)obj.PromoteNamedPropertiesToParents("company");
        Debug.WriteLine(newObj);
    }
}

输出是:

{
  "data": [
    {
      "company_ID": "12345",
      "company_location": "Some Location",
      "name": "Some Name"
    }
  ]
}

这就是你想要的。请注意,此代码创建了一个新的JObject层次结构而不是修改原始层次结构。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

展平 JToken 的相关文章

随机推荐

  • 尝试向独立 SVG 文件添加工具提示功能时,我收到“无效的‘in’操作数样式”错误

    我正在尝试将工具提示添加到独立的 SVG 文件 但它返回以下错误 TypeError invalid in operand style Break On This Error if name in style 对于以下 jquery 2 0
  • android.support.test.espresso.PerformException:在视图上执行“加载适配器数据”时出错

    我正在使用 Espresso 来测试在搜索项目 例如自动完成 时出现的列表视图 直到用户在 SearchView 中输入内容后 列表视图才会出现 即我将 ListView 设置为View VISIBLE仅当用户在 SearchView 中输
  • 空对象设计模式问题

    我最近看了这个 YouTube 教程 http www youtube com watch v hp1Y9bhail8关于空对象设计模式 尽管其中存在一些错误 例如不执行任何操作的 NullCar 会创建无限循环 但这个概念得到了很好的解释
  • 将视点转换为 MKMapView 坐标

    我的目标是将视图的左上角和右下角转换为纬度 经度坐标 这些纬度 经度坐标将用于查询仅存在于视图中的注释位置 并非全部 5000 我找到了这个Stackoverflow 上的 Objective C 技巧 http stackoverflow
  • 什么时候调用属性?

    我对某些代码感到困惑 在班级中我有一个财产 Class A ClassB objB public int TimedValue objB Timer Inside classB I have classB public int Timer
  • 推送到不同存储库时自动触发 Travis?

    有没有办法在每次推送到存储库 Y 时触发存储库 X 的 Travis CI 构建 具体来说 我希望每次有推送时都启动我的构建http github com tensorflow tensorflow http github com tens
  • 如何列出 .so 文件中的符号

    如何列出从 so 文件导出的符号 如果可能的话 我还想知道它们的来源 例如 如果它们是从静态库中提取的 我正在使用 gcc 4 0 2 如果这有什么区别的话 列出符号的标准工具是nm 你可以像这样简单地使用它 nm gD yourLib s
  • Android - 创建Word文档

    我想创建word doc 和excelAndroid 平台上的 xls 文件 对于Excel我可以使用jexeljar 但我找不到任何用于 word 文件的 API 你能告诉我是否有任何开源 免费的API可以在android平台上编写wor
  • 如何保存 Linq-to-SQL 中的更改?

    所以 这是我对这个常见问题的独特见解 我执行查询 获取对象 然后将对象传递到表单中 并使用对象中的数据填充表单 这不是通过引用传递的 然后 我编辑 通过表单 查询的对象的值 然后返回根据表单中的值构造的新对象 然后我想将其更新到数据库 At
  • Wildfly 8 AS 中的热部署位置

    在JBoss 6 AS中 热部署位置是 JBOSS HOME server default deploy我可以在其中解压 WAR 或 EAR 并更改任何配置文件的内容 并且无需重新启动即可工作 同样 在Wildfly 8 AS中 任何人都可
  • Swift 无法定位和读取属性列表 (.plist) 文件

    我在让一个简单的命令行 OSX Swift 程序从一个简单的 plist XML 文件中读取数据时遇到了一个真正的问题 事实上 该程序甚至看不到该文件 尽管它似乎存在并复制到捆绑包中 数据由一个类处理 该类旨在读取 plist 数据并将其复
  • 如何从 highcharts 制作响应式饼图

    几天以来 我一直在尝试从 highcharts 中制作一个响应式饼图 我正在从事一个中等规模的项目 有时很容易失去概览 我已经检查过了 http www angulartutorial net 2014 03 responsive high
  • 向现有 Corda 网络添加新节点

    我正在尝试在 corda 网络中添加新节点和现有节点 我是作为文档做的 但无法实现 正如文档中所述 这足以创建一个包含 node conf 的文件夹吗 如果那么它在运行引导程序时不会更新文件夹中的数据和信息 但我可以通过添加 corda 和
  • 单元测试中的修补不起作用,正在调用实际方法

    我有一个 python 文件 update baseline manifest py 现在 我正在编写单元测试 想要修补 read file 和 write file 我已经这样做了 def update baseline manifest
  • 覆盖 dll 类属性集

    我在我的项目中使用了一千个封闭的 DllClass 实例 public sealed class DllClass public DllClass public string DllClassProperty get set DllClas
  • 获取异常 JDBC 类型没有方言映射

    我是 hibernate 和 java 的新手 我正在尝试执行本机 sql 查询 但我被卡住了 任何人都可以帮助我或检查我在哪里做错了吗 我的java代码是 try trns session beginTransaction String
  • Django 和 node.js :抛出参数[1]; // 未处理的“错误”事件

    我正在尝试 Django socket io 和 node js 示例实时 Django https github com mburst django realtime tutorial git 当我尝试从浏览器发送消息时 我从节点服务器收
  • 如何绘制具有两个刻度的 x 轴?

    我想画一个有两个刻度的x轴 如下图所示 ggplot2版本可以是这样的 library ggplot2 x c 1 2 3 4 5 10 20 30 40 50 y c 1 2 2 3 4 2 1 3 5 5 You should intr
  • 无法让 Robotium 在 Android Studio 中工作

    我正在努力让 Robotium 在基于 gradle 的 Android Studio 上工作 但我找不到方法 这是我的 build gradle 文件 buildscript dependencies repositories maven
  • 展平 JToken

    假设我有以下 JToken data company ID 12345 location Some Location name Some Name 我想将此令牌传递到输出此 JToken 的 FlattenToken 函数中 data co