是否可以使用JSON对象在jq中进行嵌套查询?

时间:2019-06-04 10:19:57

标签: javascript json jq

这是我的JSON:

{  
   "A":[  
      {  
         "AT":"text"
      },
      {  
         "AT":"text2"
      }
   ],
   "B":[  
      {  
         "name":"text",
         "power":10
      },
      {  
         "name":"text1",
         "power":20
      },
      {  
         "name":"text2",
         "power":40
      }
   ]
}

我希望所有B元素都具有与A元素相同的名称。因此,在这种情况下,结果将为['text',10,'text2',40]。我尝试使用此查询[.B[] | [.name , .power][]] | map(in([.A[].AT])),但无法正常工作,这使我出错:

  

jq:错误(在23处):无法索引字符串为“ A”的字符串       退出状态5

我不知道如何解决它,但我认为它与父节点有关,它无法识别in函数中的嵌套查询。那么是否有可能用这种语言进行嵌套查询,以及如何在其他情况下(如其他函数或管道的其他情况)处理嵌套查询的问题?

PS:我在JAVASCRIPT(node.js)中工作

新问题,我有以下查询: ( .Move | map({(.name): {accuracy : .url.accuracy, damage_class: .url.damage_class.name, power : .url.power, priority: .url.priority, target: .url.target.name, type: .url.type.name, null}}) | add ) as $b | .results | select(.name=="bulba") | map(.url.moves[].move.name | [., $b[.][]]) | add

并且在没有select(.name=="bulba")

的情况下可以完美地工作
  

jq:错误(在:158):无法索引字符串为“名称”的数组

我应该用这个显示JSON吗?(因为它比上一个大一点) 但这是从这里开始的:

    {  
   "results":[  
      {  
         "name":"bulba",
         "url":{  
            "moves":[  
               {  
                  "move":{  
                     "name":"flamiche"
                  }
               }
            ]
         }
      },
      {  
         "name":"sala",
         "url":{  
            "moves":[  
               {  
                  "move":{  
                     "name":"DAMSSSS"
                  }
               }
            ]
         }
      }
   ],
   "Move":[  
      {  
         "name":"flamiche",
         "url":{  
            "accuracy":50,
            "damage_class":{  
               "name":"physical"
            },
            "power":50,
            "priority":0,
            "target":{  
               "name":"foe"
            },
            "type":{  
               "name":"fire"
            }
         }
      },
      {  
         "name":"DAMSSSS",
         "url":{  
            "accuracy":90,
            "damage_class":{  
               "name":"status"
            },
            "power":null,
            "priority":2,
            "target":{  
               "name":"self"
            },
            "type":{  
               "name":"grass"
            }
         }
      }
   ]
}

3 个答案:

答案 0 :(得分:1)

如果要获取B上的所有A对象,则可以使用Setconcat创建具有所有A值的对象。使用filter过滤对象B

var obj = {"A":[{"AT":"text"},{"AT":"text2"}],"B":[{"name":"text","power":10},{"name":"text1","power":20},{"name":"text2","power":40}]}

var allAs = new Set([].concat(...obj.A.map(o => Object.values(o))));
var result = obj.B.filter(o => allAs.has(o.name));

console.log(result);

您还可以将flatMap(在节点11.0.0上可用)用作:

var obj = {"A":[{"AT":"text"},{"AT":"text2"}],"B":[{"name":"text","power":10},{"name":"text1","power":20},{"name":"text2","power":40}]}

var allAs = new Set(obj.A.flatMap(o => Object.values(o)));
var result = obj.B.filter(o => allAs.has(o.name));

console.log(result);

答案 1 :(得分:1)

您正在将[.B[] | [.name , .power][]]的产品(将是由字符串组成的数组)传送到map(in([.A[].AT])),即输入被更改并且{{1} }丢失了,您正在尝试从这些字符串中获取.A。这不是唯一的问题,而是导致该错误的原因。您最好这样做:

.A[].AT

如果使用( .B | map({(.name): .power}) | add ) as $b | .A | map(.AT | [., $b[.]]) | add 输入的内容太大,则可以获得更好的效果:

reduce

关于第二个问题,通过将( reduce .B[] as $b ({}; . + ($b | {(.name): .power})) ) as $b | reduce .A[].AT as $a ([]; . + [$a, $b[$a]]) (对象数组)传递给results,因为错误消息指出您正在尝试使用字符串对数组进行索引。要过滤select(.name=="bulba")下的对象,请像这样将results移到select中:

map

答案 2 :(得分:0)

如果对替代(非jq)解决方案感兴趣,可以采用一种新颖的方法来实现-使用基于步行路径的Unix实用程序 jtc ,该逻辑主要是编码到JSON树中:

bash $ <file.json jtc -x'[A][:][AT]<at>v[^0][B][name]:<at>s' -y' ' -y'[-1][power]' -jr
[ "text", 10, "text2", 40 ]
bash $ 

步行路径(-w)细分:

  • [A][:][AT]<at>v-从根开始,通过标签A地址JSON,然后在其中记录([:]),然后为每个记录地址标签AT记忆在名称空间at
  • 中找到的值
  • [^0][B][name]:<at>s-重置返回的根([^0]),通过标签B地址JSON,然后(在B中)搜索存储在命名空间{中的值{1}}的标签为at

-这样,它将找到A中所有发生在B中的条目name

现在

-AT只是一个空串联(-y' '与每个-x串联),因此该选项可确保打印找到每个文本(-y)的值

-AT然后将与-y'[-1][power]'串联的选项传递相同的值,但最后将在JSON树中上移1级/层,并通过-x标签选择值

最后,所有经过的条目将使用power选项包装回int JSON数组

更新:更简单的解决方案(只需步行一次而不是两次):

-j

PS>披露:我是bash $ <file.json jtc -w'<AT>l:<at>v[^0][name]:<at>s[-1][:]' -jr [ "text", 10, "text2", 40 ] bash $ -用于JSON操作的shell cli工具的创建者