ansible/jmespath/jq를 사용하여 이스케이프된 json 문자열을 구문 분석하는 방법은 무엇입니까?

ansible/jmespath/jq를 사용하여 이스케이프된 json 문자열을 구문 분석하는 방법은 무엇입니까?

저는 Bluecat의 Ansible 모듈을 사용하여 서브넷에 대한 일부 정보를 얻기 위한 인증 API 호출을 만들고 있습니다. 응답은 다음과 같습니다.

"result": {
        "changed": false,
        "failed": false,
        "json": "b'{\"id\":12345,\"name\":\"SUBNET NAME\",\"properties\":\"CIDR=10.2.2.0/24|allowDuplicateHost=enable|pingBeforeAssign=disable|inheritAllowDuplicateHost=true|inheritPingBeforeAssign=true|gateway=10.2.2.1|inheritDNSRestrictions=true|inheritDefaultDomains=true|inheritDefaultView=true|\",\"type\":\"IP4Network\"}\\n'",
        "msg": "",
        "status": 200
}

보시다시피 유용한 데이터는 모두 필드에 있지만 json이스케이프된 따옴표와 개행 문자가 포함된 불쾌한 문자열 리터럴입니다. 내가 달리면

- debug:
      msg: "{{ result | json_query('json.name') }}"

Ansible에서는 msg대신 필드를 제공합니다! 전체 json필드를 얻을 수 있지만 내용은 전혀 얻을 수 없습니다. 약간 수정하고 b시작 부분의 추가 백슬래시, 내부 작은따옴표, 끝 부분의 개행 문자를 잘라내면 jq .json | fromjson올바르게 구문 분석됩니다. 하지만 나는 그것이 단지 바이트 인코딩을 의미하고 구문 분석을 중단해서는 안 된다고 확신 b''하지만 그렇습니다. 끝에 이중 백슬래시는 어떻게 되나요?

sed탈출한 모든 캐릭터를 죽이기 위해 흑마법을 사용하는 것 외에 다른 옵션이 있습니까? Web API가 왜 그러한 문자열을 반환합니까?

답변1

중괄호 밖의 내용을 제거하면 {}Ansible이 사전을 구문 분석합니다.

  subnet: "{{ result.json[2:-3] }}"

주어진

  subnet:
    id: 12345
    name: SUBNET NAME
    properties: CIDR=10.2.2.0/24|allowDuplicateHost=enable|pingBeforeAssign=disable|inheritAllowDuplicateHost=true|inheritPingBeforeAssign=true|gateway=10.2.2.1|inheritDNSRestrictions=true|inheritDefaultDomains=true|inheritDefaultView=true|
    type: IP4Network

선택적으로 보다 강력한 스트라이핑을 사용합니다. 예를 들어 다음 표현식은 동일한 결과를 제공합니다.

  subnet: "{{ result.json|regex_replace(_regex, _replace) }}"
  _regex: '^.*?\{(.*)\}.*$'
  _replace: '{\1}'

속성을 구문 분석하려는 경우특성마찬가지로 다음 표현식도

  subnet_prop: "{{ subnet|combine({'properties': dict(_prop)}) }}"
  _prop: "{{ subnet.properties.split('|')|select|map('split', '=')|list }}"

주어진

  subnet_prop:
    id: 12345
    name: SUBNET NAME
    properties:
      CIDR: 10.2.2.0/24
      allowDuplicateHost: enable
      gateway: 10.2.2.1
      inheritAllowDuplicateHost: 'true'
      inheritDNSRestrictions: 'true'
      inheritDefaultDomains: 'true'
      inheritDefaultView: 'true'
      inheritPingBeforeAssign: 'true'
      pingBeforeAssign: disable
    type: IP4Network

부울 값은 위 사전에서 문자열로 표시됩니다. 이것이 문제라면 교체하세요나뉘다필터정규식_교체그리고from_yaml. 필터도 그런 경우나뉘다없는

  _prop: "{{ subnet.properties.split('|')|
             select|
             map('regex_replace', '^(.*)=(.*)$', '[\\1, \\2]')|
             map('from_yaml')|list }}"

주어진

  subnet_prop:
    id: 12345
    name: SUBNET NAME
    properties:
      CIDR: 10.2.2.0/24
      allowDuplicateHost: enable
      gateway: 10.2.2.1
      inheritAllowDuplicateHost: true
      inheritDNSRestrictions: true
      inheritDefaultDomains: true
      inheritDefaultView: true
      inheritPingBeforeAssign: true
      pingBeforeAssign: disable
    type: IP4Network

관련 정보