如何在许多 object 中插入具有动态值的属性或在许多数组中动态添加元素?
How to insert a attribute with a dynamic value in many object or add an element dynamically in many array?
我想在许多 object(位于数组中)中添加一个属性,这个值将被动态获取。我使用下面的 JSON ,并且我已经进行了查询以提取我想要的内容。我们将从该查询的结果开始。
首先我整个JSON:
[
{
"Nature":"lol",
"EV":"lol",
"Moves":[
{
"Move":"OHKOmove",
"Max":100,
"Min":15
},
{
"Move":"cacaz",
"Max":35,
"Min":20
}
]
},
{
"Nature":"loi",
"EV":"lal",
"Moves":[
{
"Move":"caca1",
"Max":100,
"Min":3
},
{
"Move":"caca2",
"Max":100,
"Min":3
}
]
},
{
"Nature":"loi2",
"EV":"lal",
"Moves":[
{
"Move":"caca1",
"Max":100,
"Min":3
},
{
"Move":"caca2",
"Max":100,
"Min":3
},
{
"Move":"caca3",
"Max":100,
"Min":3
}
]
},
{
"Nature":"loi3",
"EV":"lil",
"Moves":[
{
"Move":"caca1",
"Max":100,
"Min":3
},
{
"Move":"caca2",
"Max":100,
"Min":3
},
{
"Move":"caca3",
"Max":100,
"Min":3
}
]
}
]
然后我的查询:[?(length(Moves[?Max == `100`]) > `1`)].{Nature: Nature, EV: EV, Moves: Moves[?Max == `100`].Move, MovesCount: length(Moves[?Max == `100`].Move)} | [@,{MaxMouvCount: max_by(@, &MovesCount).MovesCount}][]
我的查询结果是这样的:
JSON 格式示例 1
[
{
"Nature": "loi",
"EV": "lal",
"Moves": [
"caca1",
"caca2"
],
"MovesCount": 2
},
{
"Nature": "loi2",
"EV": "lal",
"Moves": [
"caca1",
"caca2",
"caca3"
],
"MovesCount": 3
},
{
"Nature": "loi3",
"EV": "lil",
"Moves": [
"caca1",
"caca2",
"caca3"
],
"MovesCount": 3
},
{
"MaxMouvCount": 3
}
]
想法是将属性 "MaxMouvCount": 3
放在数组中的每个 object 上,然后将其从数组中删除,得到如下结果:
JSON 格式示例 2
[
{
"Nature": "loi",
"EV": "lal",
"Moves": [
"caca1",
"caca2"
],
"MovesCount": 2,
"MaxMouvCount": 3
},
{
"Nature": "loi2",
"EV": "lal",
"Moves": [
"caca1",
"caca2",
"caca3"
],
"MovesCount": 3,
"MaxMouvCount": 3
},
{
"Nature": "loi3",
"EV": "lil",
"Moves": [
"caca1",
"caca2",
"caca3"
],
"MovesCount": 3,
"MaxMouvCount": 3
}
]
在标题中我谈到了数组,实际上在我查询之后使用 .*
我可以转换数组中的 object 并且可能更容易地在每个数组中放置值(与 [= 匹配42=]s) 并使用 object 构造函数将数组重新转换为 object 。但我不知道该怎么做。你能帮我一下吗,或者如果可能的话至少告诉我一下。
PS:我只使用 JMESPath,所以我不想用任何其他包含 JMESPath 代码的语言(比如 javascript(在我的例子中)或 python 或别的)
快速回答 (TL;DR)
- 通常使用 JMESPath 很容易无痛地转换 JSON
- 一个轻松的关键是利用 JSON 结构,这些结构经过专门规范化以最佳地与 JMESPath
一起使用
- 一个轻松的关键是知道何时在 JSON 中使用字典(又名对象 // 关联数组 // 映射)名称-值对来制作 JSON 的所有部分能够明确引用
- 不幸的是,这个特定问题的目标是无法使用标准 JMESPath,因为 JMESPath 缺少引用 JSON 数据根的标记
current-node
上下文
详细解答
上下文
- JMESPath 查询语言
python 3.x
使用 JMESPath 0.9.4
[但任何 JMESPath 引擎都可以]
问题
- 场景:
- DeveloperSObosskay972 希望将 JSON 数据从一种表示形式转换为另一种表示形式
- DeveloperSObosskay972 想完全依靠 JMESPath 表达式来完成转换
- DeveloperSObosskay972 想在另一部分引用 JSON 结构的一部分,以允许动态交叉引用数据结构
尝试 01(不是我们真正想要的)
- "almost" 不是我们想要的解决方案
- 此代码...
import jmespath
vdata001aa = """<<json.load(JSON Format Example 1)>>"""
vresult = jmespath.compile('@|[*].{"Nature":@.Nature,"EV":@.EV,"Moves":@.Moves,"MovesCount":@.MovesCount,"MaxMouvCount":`3`}').search(vdata001aa)
pprint.pprint(vresult)
- 产生这个结果...
[{'EV': 'lal',
'MaxMouvCount': 3,
'Moves': ['caca1', 'caca2'],
'MovesCount': 2,
'Nature': 'loi'},
{'EV': 'lal',
'MaxMouvCount': 3,
'Moves': ['caca1', 'caca2', 'caca3'],
'MovesCount': 3,
'Nature': 'loi2'},
{'EV': 'lil',
'MaxMouvCount': 3,
'Moves': ['caca1', 'caca2', 'caca3'],
'MovesCount': 3,
'Nature': 'loi3'},
{'EV': None,
'MaxMouvCount': 3,
'Moves': None,
'MovesCount': None,
'Nature': None}]
- 这不是我们想要的,因为:
- 我们必须硬连线
MaxMouvCount
的值 3
,技术上是 "cheating"
- 这是作弊,因为我们想要一个动态值,而不是硬连线值
- 这会产生一个多余的元素,其中除 MaxMouvCount 之外的每个值都是
null
(python 恰好称其为 None
)
- 我们只想要三个元素,而不是四个
尝试 02(不是我们真正想要的)
- Attempt 01 运行不佳的原因是原始 JSON 结构未针对 JMESPath
规范化
- 为了解决这个问题,我们将字典名称-值对添加到原始数据中
- 通过这种方法,我们使 JSON 数据的 每个元素 成为附加到字典键(又名 javascript 对象名称-值对)的值)
- 这里我们使用术语
dictionary
,在其他上下文中称为 object
或 hash
或 associative array
或 mapping
- 我们不关心术语,只关心将顶级 JSON 的所有部分作为名称-值对
引用的能力
尝试 02 // 第 1 部分(重新格式化 JSON 格式示例 1)
- 重新格式化您的原始 JSON
JSON Format Example 1
使其看起来像这样
- 这种重新格式化的 JSON 将使您数据的所有部分都可以明确寻址
{
"jsontop": {
"settings_info": {
"MaxMouvCount": 3
},
"nature_table": [
{
"Nature": "loi",
"EV": "lal",
"Moves": [
"caca1",
"caca2"
],
"MovesCount": 2
},
{
"Nature": "loi2",
"EV": "lal",
"Moves": [
"caca1",
"caca2",
"caca3"
],
"MovesCount": 3
},
{
"Nature": "loi3",
"EV": "lil",
"Moves": [
"caca1",
"caca2",
"caca3"
],
"MovesCount": 3
}
]
}
尝试 02 // 第 2 部分(运行 轻松的 JMESPath 查询以获得您想要的内容)
- 此代码...
import jmespath
vdata001aa = """<<json.load(**RE-NORMALIZED** JSON Format Example 1)>>"""
vresult = jmespath.compile('@|jsontop.nature_table[*].{"Nature":@.Nature,"EV":@.EV,"Moves":@.Moves,"MovesCount":@.MovesCount,"MaxMouvCount":jsontop.settings_info.MaxMouvCount}').search(vdata001aa)
pprint.pprint(vresult)
pass
- 产生这个结果...
[{'EV': 'lal',
'MaxMouvCount': None,
'Moves': ['caca1', 'caca2'],
'MovesCount': 2,
'Nature': 'loi'},
{'EV': 'lal',
'MaxMouvCount': None,
'Moves': ['caca1', 'caca2', 'caca3'],
'MovesCount': 3,
'Nature': 'loi2'},
{'EV': 'lil',
'MaxMouvCount': None,
'Moves': ['caca1', 'caca2', 'caca3'],
'MovesCount': 3,
'Nature': 'loi3'}]
- 这不是我们想要的,因为我们在预期
3
的地方得到了 None
(又名 null
)
说明
- 尝试 02 会 有效,如果 JMESPath 支持一个标记来引用 JSON 根对象
- 另一个可行的查询是(例如,如果美元符号字符用作对 JSON 数据根的引用)
import jmespath
vdata001aa = """<<json.load(**RE-NORMALIZED** JSON Format Example 1)>>"""
vresult = jmespath.compile('@|jsontop.nature_table[*].{"Nature":@.Nature,"EV":@.EV,"Moves":@.Moves,"MovesCount":@.MovesCount,"MaxMouvCount":$.jsontop.settings_info.MaxMouvCount}').search(vdata001aa)
pprint.pprint(vresult)
pass
- GitHub 上实际上有一个解决 JMESPath 限制的项目
结论
- Attempt 01和Attempt 02表明当前(稳定)版本的JMESPath并不能完全满足要求
- 您必须脱离 JMESPath 才能从 JSON 中获取所需的动态值并填充重新格式化的数据
- 或者,您必须向 JMESPath 本身添加一个扩展,这可能不如使用托管语言的功能更令人满意
我想在许多 object(位于数组中)中添加一个属性,这个值将被动态获取。我使用下面的 JSON ,并且我已经进行了查询以提取我想要的内容。我们将从该查询的结果开始。
首先我整个JSON:
[
{
"Nature":"lol",
"EV":"lol",
"Moves":[
{
"Move":"OHKOmove",
"Max":100,
"Min":15
},
{
"Move":"cacaz",
"Max":35,
"Min":20
}
]
},
{
"Nature":"loi",
"EV":"lal",
"Moves":[
{
"Move":"caca1",
"Max":100,
"Min":3
},
{
"Move":"caca2",
"Max":100,
"Min":3
}
]
},
{
"Nature":"loi2",
"EV":"lal",
"Moves":[
{
"Move":"caca1",
"Max":100,
"Min":3
},
{
"Move":"caca2",
"Max":100,
"Min":3
},
{
"Move":"caca3",
"Max":100,
"Min":3
}
]
},
{
"Nature":"loi3",
"EV":"lil",
"Moves":[
{
"Move":"caca1",
"Max":100,
"Min":3
},
{
"Move":"caca2",
"Max":100,
"Min":3
},
{
"Move":"caca3",
"Max":100,
"Min":3
}
]
}
]
然后我的查询:[?(length(Moves[?Max == `100`]) > `1`)].{Nature: Nature, EV: EV, Moves: Moves[?Max == `100`].Move, MovesCount: length(Moves[?Max == `100`].Move)} | [@,{MaxMouvCount: max_by(@, &MovesCount).MovesCount}][]
我的查询结果是这样的:
JSON 格式示例 1
[
{
"Nature": "loi",
"EV": "lal",
"Moves": [
"caca1",
"caca2"
],
"MovesCount": 2
},
{
"Nature": "loi2",
"EV": "lal",
"Moves": [
"caca1",
"caca2",
"caca3"
],
"MovesCount": 3
},
{
"Nature": "loi3",
"EV": "lil",
"Moves": [
"caca1",
"caca2",
"caca3"
],
"MovesCount": 3
},
{
"MaxMouvCount": 3
}
]
想法是将属性 "MaxMouvCount": 3
放在数组中的每个 object 上,然后将其从数组中删除,得到如下结果:
JSON 格式示例 2
[
{
"Nature": "loi",
"EV": "lal",
"Moves": [
"caca1",
"caca2"
],
"MovesCount": 2,
"MaxMouvCount": 3
},
{
"Nature": "loi2",
"EV": "lal",
"Moves": [
"caca1",
"caca2",
"caca3"
],
"MovesCount": 3,
"MaxMouvCount": 3
},
{
"Nature": "loi3",
"EV": "lil",
"Moves": [
"caca1",
"caca2",
"caca3"
],
"MovesCount": 3,
"MaxMouvCount": 3
}
]
在标题中我谈到了数组,实际上在我查询之后使用 .*
我可以转换数组中的 object 并且可能更容易地在每个数组中放置值(与 [= 匹配42=]s) 并使用 object 构造函数将数组重新转换为 object 。但我不知道该怎么做。你能帮我一下吗,或者如果可能的话至少告诉我一下。
PS:我只使用 JMESPath,所以我不想用任何其他包含 JMESPath 代码的语言(比如 javascript(在我的例子中)或 python 或别的)
快速回答 (TL;DR)
- 通常使用 JMESPath 很容易无痛地转换 JSON
- 一个轻松的关键是利用 JSON 结构,这些结构经过专门规范化以最佳地与 JMESPath 一起使用
- 一个轻松的关键是知道何时在 JSON 中使用字典(又名对象 // 关联数组 // 映射)名称-值对来制作 JSON 的所有部分能够明确引用
- 不幸的是,这个特定问题的目标是无法使用标准 JMESPath,因为 JMESPath 缺少引用 JSON 数据根的标记
current-node
上下文
详细解答
上下文
- JMESPath 查询语言
python 3.x
使用JMESPath 0.9.4
[但任何 JMESPath 引擎都可以]
问题
- 场景:
- DeveloperSObosskay972 希望将 JSON 数据从一种表示形式转换为另一种表示形式
- DeveloperSObosskay972 想完全依靠 JMESPath 表达式来完成转换
- DeveloperSObosskay972 想在另一部分引用 JSON 结构的一部分,以允许动态交叉引用数据结构
尝试 01(不是我们真正想要的)
- "almost" 不是我们想要的解决方案
- 此代码...
import jmespath
vdata001aa = """<<json.load(JSON Format Example 1)>>"""
vresult = jmespath.compile('@|[*].{"Nature":@.Nature,"EV":@.EV,"Moves":@.Moves,"MovesCount":@.MovesCount,"MaxMouvCount":`3`}').search(vdata001aa)
pprint.pprint(vresult)
- 产生这个结果...
[{'EV': 'lal',
'MaxMouvCount': 3,
'Moves': ['caca1', 'caca2'],
'MovesCount': 2,
'Nature': 'loi'},
{'EV': 'lal',
'MaxMouvCount': 3,
'Moves': ['caca1', 'caca2', 'caca3'],
'MovesCount': 3,
'Nature': 'loi2'},
{'EV': 'lil',
'MaxMouvCount': 3,
'Moves': ['caca1', 'caca2', 'caca3'],
'MovesCount': 3,
'Nature': 'loi3'},
{'EV': None,
'MaxMouvCount': 3,
'Moves': None,
'MovesCount': None,
'Nature': None}]
- 这不是我们想要的,因为:
- 我们必须硬连线
MaxMouvCount
的值3
,技术上是 "cheating"- 这是作弊,因为我们想要一个动态值,而不是硬连线值
- 这会产生一个多余的元素,其中除 MaxMouvCount 之外的每个值都是
null
(python 恰好称其为None
) - 我们只想要三个元素,而不是四个
- 我们必须硬连线
尝试 02(不是我们真正想要的)
- Attempt 01 运行不佳的原因是原始 JSON 结构未针对 JMESPath 规范化
- 为了解决这个问题,我们将字典名称-值对添加到原始数据中
- 通过这种方法,我们使 JSON 数据的 每个元素 成为附加到字典键(又名 javascript 对象名称-值对)的值)
- 这里我们使用术语
dictionary
,在其他上下文中称为object
或hash
或associative array
或mapping
- 我们不关心术语,只关心将顶级 JSON 的所有部分作为名称-值对 引用的能力
- 这里我们使用术语
- 重新格式化您的原始 JSON
JSON Format Example 1
使其看起来像这样 - 这种重新格式化的 JSON 将使您数据的所有部分都可以明确寻址
{
"jsontop": {
"settings_info": {
"MaxMouvCount": 3
},
"nature_table": [
{
"Nature": "loi",
"EV": "lal",
"Moves": [
"caca1",
"caca2"
],
"MovesCount": 2
},
{
"Nature": "loi2",
"EV": "lal",
"Moves": [
"caca1",
"caca2",
"caca3"
],
"MovesCount": 3
},
{
"Nature": "loi3",
"EV": "lil",
"Moves": [
"caca1",
"caca2",
"caca3"
],
"MovesCount": 3
}
]
}
尝试 02 // 第 2 部分(运行 轻松的 JMESPath 查询以获得您想要的内容)
- 此代码...
import jmespath
vdata001aa = """<<json.load(**RE-NORMALIZED** JSON Format Example 1)>>"""
vresult = jmespath.compile('@|jsontop.nature_table[*].{"Nature":@.Nature,"EV":@.EV,"Moves":@.Moves,"MovesCount":@.MovesCount,"MaxMouvCount":jsontop.settings_info.MaxMouvCount}').search(vdata001aa)
pprint.pprint(vresult)
pass
- 产生这个结果...
[{'EV': 'lal',
'MaxMouvCount': None,
'Moves': ['caca1', 'caca2'],
'MovesCount': 2,
'Nature': 'loi'},
{'EV': 'lal',
'MaxMouvCount': None,
'Moves': ['caca1', 'caca2', 'caca3'],
'MovesCount': 3,
'Nature': 'loi2'},
{'EV': 'lil',
'MaxMouvCount': None,
'Moves': ['caca1', 'caca2', 'caca3'],
'MovesCount': 3,
'Nature': 'loi3'}]
- 这不是我们想要的,因为我们在预期
3
的地方得到了
None
(又名 null
)
说明
- 尝试 02 会 有效,如果 JMESPath 支持一个标记来引用 JSON 根对象
- 另一个可行的查询是(例如,如果美元符号字符用作对 JSON 数据根的引用)
import jmespath
vdata001aa = """<<json.load(**RE-NORMALIZED** JSON Format Example 1)>>"""
vresult = jmespath.compile('@|jsontop.nature_table[*].{"Nature":@.Nature,"EV":@.EV,"Moves":@.Moves,"MovesCount":@.MovesCount,"MaxMouvCount":$.jsontop.settings_info.MaxMouvCount}').search(vdata001aa)
pprint.pprint(vresult)
pass
- GitHub 上实际上有一个解决 JMESPath 限制的项目
结论
- Attempt 01和Attempt 02表明当前(稳定)版本的JMESPath并不能完全满足要求
- 您必须脱离 JMESPath 才能从 JSON 中获取所需的动态值并填充重新格式化的数据
- 或者,您必须向 JMESPath 本身添加一个扩展,这可能不如使用托管语言的功能更令人满意