bash 如何在bash中将json响应转换为yaml

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/53315791/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 17:03:02  来源:igfitidea点击:

How to convert a json response into yaml in bash

jsonbashyamljq

提问by Jan

I read data from a json file with jq. I wanna append the results into a yaml file, but I dont get it working. I am quite new to shell programming. My goal is to append that "users" to an existing "users"-Array in a yaml file.

我用 jq 从一个 json 文件中读取数据。我想将结果附加到 yaml 文件中,但我无法正常工作。我对 shell 编程很陌生。我的目标是将该“用户”附加到 yaml 文件中现有的“用户”数组。

This is my json file:

这是我的 json 文件:

#$DEFAULTS_FILE

{"users":
  [
    {"name":"pi",
      "gecos": "Hypriot Pirate",
      "sudo":"ALL=(ALL) NOPASSWD:ALL",
      "shell": "/bin/bash",
      "groups":"users,docker,video",
      "plain_text_passwd":"pi",
      "lock_passwd":"false",
      "ssh_pwauth":"true",
      "chpasswd": {"expire": false}
    },
    {"name":"admin",
      "gecos": "Hypriot Pirate",
      "sudo":"ALL=(ALL) NOPASSWD:ALL",
      "shell": "/bin/bash",
      "primary-group": "users",
      "groups":"users,docker,adm,dialout,audio,plugdev,netdev,video",
      "ssh-import-id":"None",
      "plain_text_passwd":"pi",
      "lock_passwd":"true",
      "ssh_pwauth":"true",
      "chpasswd": "{expire: false}",
      "ssh-authorized-keys": ["ssh-rsa abcdefg1234567890 [email protected]"]
    }
  ]
  }

I filter it with that:

我用它过滤它:

cat $DEFAULTS_FILE | jq .users

cat $DEFAULTS_FILE | jq .users

I have no clue how to convert that json into a yaml.

我不知道如何将该 json 转换为 yaml。

My expected result should be:

我的预期结果应该是:

users:
  - name:                pi
    gecos:               "Hypriot Pirate"
    sudo:                ALL=(ALL) NOPASSWD:ALL
    shell:               /bin/bash
    groups:              users,docker,video
    plain_text_passwd:   pi
    lock_passwd:         false
    ssh_pwauth:          true
    chpasswd: { expire:  false }
  - name:                admin
    primary-group:       users
    shell:               /bin/bash
    sudo:                ALL=(ALL) NOPASSWD:ALL
    groups:              users,docker,adm,dialout,audio,plugdev,netdev,video
    ssh-import-id:       None

I tried to use a second tool called yqwhich is similar to jqand can write yaml files. But I have no positive progress.

我尝试使用yq类似于jq并且可以编写 yaml 文件的第二个工具。但我没有任何积极的进展。

EDIT

编辑

I know that I can add content to the yaml with that:

我知道我可以通过以下方式向 yaml 添加内容:

yq w -i "my.yml" "users[+]" "some content"

yq w -i "my.yml" "users[+]" "some content"

But I dont know how to merge my json into that.

但我不知道如何将我的 json 合并到其中。

Any help or hint would be nice, thank you in advance...

任何帮助或提示都会很好,提前谢谢...

回答by Jeff Mercado

I'm not sure what rules you're using to get to your expected result. It seems like you're randomly applying different rules to how the values are being converted.

我不确定您使用什么规则来获得预期结果。似乎您对值的转换方式随机应用了不同的规则。

As I understand it, scalar values are just output as is (with potential encoding), objects are output as key/value pairs, and array objects are output with a -for every item. The indentation associates what's part of what.

据我了解,标量值只是按原样输出(具有潜在的编码),对象作为键/值对输出,数组对象输出-为每个项目。缩进关联什么是什么的一部分。

So based on those rules if you're going to use jq:

因此,如果您要使用 jq,请根据这些规则:

def yamlify:
    (objects | to_entries[] | (.value | type) as $type |
        if $type == "array" then
            "\(.key):", (.value | yamlify)
        elif $type == "object" then
            "\(.key):", "    \(.value | yamlify)"
        else
            "\(.key):\t\(.value)"
        end
    )
    // (arrays | select(length > 0)[] | [yamlify] |
        "  - \(.[0])", "    \(.[1:][])"
    )
    // .
    ;

Then to use it, add it to your .jqfile and use it:

然后使用它,将它添加到您的.jq文件中并使用它:

$ jq -r yamlify input.json
users:
  - name:       pi
    gecos:      Hypriot Pirate
    sudo:       ALL=(ALL) NOPASSWD:ALL
    shell:      /bin/bash
    groups:     users,docker,video
    plain_text_passwd:  pi
    lock_passwd:        false
    ssh_pwauth: true
    chpasswd:
        expire: false
  - name:       admin
    gecos:      Hypriot Pirate
    sudo:       ALL=(ALL) NOPASSWD:ALL
    shell:      /bin/bash
    primary-group:      users
    groups:     users,docker,adm,dialout,audio,plugdev,netdev,video
    ssh-import-id:      None
    plain_text_passwd:  pi
    lock_passwd:        true
    ssh_pwauth: true
    chpasswd:   {expire: false}
    ssh-authorized-keys:
      - ssh-rsa abcdefg1234567890 [email protected]


Here's another variation that aligns the values

这是对齐值的另一个变体

def yamlify2:
    (objects | to_entries | (map(.key | length) | max + 2) as $w |
        .[] | (.value | type) as $type |
        if $type == "array" then
            "\(.key):", (.value | yamlify2)
        elif $type == "object" then
            "\(.key):", "    \(.value | yamlify2)"
        else
            "\(.key):\(" " * (.key | $w - length))\(.value)"
        end
    )
    // (arrays | select(length > 0)[] | [yamlify2] |
        "  - \(.[0])", "    \(.[1:][])"
    )
    // .
    ;
$ jq -r yamlify2 input.json
users:
  - name:               pi
    gecos:              Hypriot Pirate
    sudo:               ALL=(ALL) NOPASSWD:ALL
    shell:              /bin/bash
    groups:             users,docker,video
    plain_text_passwd:  pi
    lock_passwd:        false
    ssh_pwauth:         true
    chpasswd:
        expire:  false
  - name:                 admin
    gecos:                Hypriot Pirate
    sudo:                 ALL=(ALL) NOPASSWD:ALL
    shell:                /bin/bash
    primary-group:        users
    groups:               users,docker,adm,dialout,audio,plugdev,netdev,video
    ssh-import-id:        None
    plain_text_passwd:    pi
    lock_passwd:          true
    ssh_pwauth:           true
    chpasswd:             {expire: false}
    ssh-authorized-keys:
      - ssh-rsa abcdefg1234567890 [email protected]

回答by Pavel

I've used ruby to write my json content into yaml.

我使用 ruby​​ 将我的 json 内容写入 yaml。

As for your example, it can be achieved like this:

至于你的例子,它可以这样实现:

cat $DEFAULTS_FILE | jq .users | ruby -ryaml -rjson -e 'puts YAML.dump(JSON.parse(STDIN.read))' > my.yml

回答by Richard Gomes

function yaml_validate {
  python -c 'import sys, yaml, json; yaml.safe_load(sys.stdin.read())'
}

function yaml2json {
  python -c 'import sys, yaml, json; print(json.dumps(yaml.safe_load(sys.stdin.read())))'
}

function yaml2json_pretty {
  python -c 'import sys, yaml, json; print(json.dumps(yaml.safe_load(sys.stdin.read()), indent=2, sort_keys=False))'
}

function json_validate {
  python -c 'import sys, yaml, json; json.loads(sys.stdin.read())'
}

function json2yaml {
  python -c 'import sys, yaml, json; print(yaml.dump(json.loads(sys.stdin.read())))'
}

More Bash tricks at http://github.com/frgomes/bash-scripts

更多 Bash 技巧,请访问http://github.com/frgomes/bash-scripts

回答by Sebastian Wagner

Another oneliner:

另一个单线:

python -c 'import yaml, sys; print(yaml.dump(yaml.load(open(sys.argv[1])), default_flow_style=False))' input.json

(exploiting the fact that valid json is also valid yaml)

(利用有效的 json 也是有效的 yaml 的事实)

And yaml to json:

和 yaml 到 json:

python -c 'import yaml, json, sys; print(json.dumps(yaml.load(open(sys.argv[1])), indent=2))' input.yaml

回答by YVrancken

I'v been able to get the result using the following command:

我已经能够使用以下命令获得结果:

jq -r .users defaultsfile.txt >> users.yaml

The output is in clear yaml format.

输出采用清晰的 yaml 格式。