jq试图迭代两组值

时间:2017-02-09 01:36:16

标签: json jq

更新:我已尝试提取我想要更新的路径,并在setpath(路径; getpath(路径))构造中使用相对于本地和返回对象(如下所示)的路径。我现在可以遍历$ paths数组并对本地json对象进行所需的更新。

使用下面的thermostats2.json文件和一个与thermostats2.json不同的ret.json:

{“location”:{“livingroom”:{“setpoints”:{“day”:“25000”}}}} #vs {“day”:“23000”}

我的脚本现在看起来像:

. as $obj |

# obtain location keys from $obj as they may have changed locally prior to $retobj being processed

($obj.location | keys? ) as $locs |

# setpoints are fixed in this code as ["day","night","away"]

["day","night","away"] as $setpoints |

[path($obj.location[($locs[])].setpoints[($setpoints[])])] as $paths |

reduce
  range(0; $paths|length) as $i
(.; . | setpath($paths[$i];( $retobj[0] | getpath($paths[$i])))  ) | .

此时我不需要$ obj变量,但我还没有清理过它。如果您发现此方法存在问题或者这看起来是一个很好的解决方案,请发表评论。如果评论表明它应该是,我会回答这个问题。

我有一个json对象,它包含多个位置对象,每个位置对象包含几个设定点对象,以及其他数据。如果需要,将为此json对象提供远程应用程序,并将更新返回给设定点对象的值。我想更新本地json对象,而不是用返回的对象替换它。

我不想假设返回对象的位置键与本地对象的位置键相同,因为在修改远程对象时可能已经维护了本地对象。

我已经想出如何从本地文件中提取位置键,并创建一个包含我感兴趣的值更新的设定值键的数组。我还能够弄清楚如何将返回对象的更新值减少为数组。

我还没想到的是如何迭代位置和设定点以便更新本地json对象中的值。

我用:

调用jq
# usage : jq --slurpfile retobj ret.json --from-file query.jq thermostats2.json

query.jq contains:
# use $obj as the local object to be updated with values returned in $retobj
# $retobj is not permitted to modify the structure of $obj

. as $obj |

# obtain location keys from $obj as they may have changed locally prior to $retobj being processed

($obj.location | keys? ) as $locs |

# setpoints are fixed in this code as ["day","night","away"]

["day","night","away"] as $setpoints |
reduce $retobj[0].location[($locs[])].setpoints[($setpoints[])] as $item
( []; . + [$item] )
 | . as $vals |
$vals

thermostats2.json:

{ "mode":"Home",
  "location": {
    "livingroom": {
    "scale":"Celcius",
    "current": {
        "valid":"YES",
        "reading":"23000",
        "time":"000000"
    },
    "previous": {
        "reading":"23000",
        "time":"000000"
    },
    "setpoints": {
        "schedule": {
        "weekday": {"day":"0600",
                "night":"2100"
               },
        "weekend": {"day":"0630",
                "night":"2200"
               }
        },
        "active":"day",
        "day":"23000",
        "night":"15556",
        "away":"12778"
    }
    },
    "familyroom": {
    "scale":"Celcius",
    "current": {
        "valid":"YES",
        "reading":"23000",
        "time":"000000"
    },
    "previous": {
        "reading":"23000",
        "time":"000000"
    },
    "setpoints": {
        "schedule": {
        "weekday": {"day":"0600",
                "night":"2100"
               },
        "weekend": {"day":"0630",
                "night":"2200"
               }

        },
        "active":"day",
        "day":"23000",
        "night":"15556",
        "away":"12778"
    }
    },
    "28-000005e2fdef": {
    "scale":"Celcius",
    "current": {
        "valid":"YES",
        "reading":"23000",
        "time":"000000"
    },
    "previous": {
        "reading":"23000",
        "time":"000000"
    },
    "setpoints": {
        "schedule": {
        "weekday": {"day":"0600",
                "night":"2100"
               },
        "weekend": {"day":"0630",
                "night":"2200"
               }
        },
        "active":"day",
        "day":"23000",
        "night":"15556",
        "away":"12778"
    }
    }
  }
}

我找不到的是在$ obj中设置相同对象的值的任何方法,即有效:

$ obj [0] .location [($ locs [])]。setpoints [($ setpoints [])] = $ vals

据我所知,作为新手,我不太可能选择解决此类问题的首选方法。我也在努力在一些内置函数中使用过滤器范例,特别是foreach。

回顾我的目标,我希望:

通过从本地obj派生的位置键和过滤器中定义的设定点键在$ retobj中获取正确的对象值,并将本地对象中的相同路径设置为这些值。

1 个答案:

答案 0 :(得分:0)

基于我对这个问题的理解,我相信使用--argfile而不是--slurpfile可以简化事情。

以下过滤器将根据thermostats2.json的内容调整$ retobj:

. as $in
| reduce ["location",
          (.location | keys[]),
          "setpoints",
          ["day","night","away"][]] as $path
    ( $retobj;
      setpath( $path; ($in | getpath($path)) ) )

调用:     jq --argfile retobj ret.json -f query.jq thermostats2.json