Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to convert escaped Json into regular Json or variable?

I’m using Ansible to pull the contents of a JSON file from Bitbucket. The problem is the content is escaped JSON so I can’t use it in a variable or parse it, etc. Here’s an example of what I get back from Bitbucket:

{
    "json": {
      "lines": [
            {
            "text": "    \"AWS\": {"
            },
            {
            "text": "        \"S3\": {"
            },
            {
            "text": "            \"Bucket\": \"my-s3-bucket\","
            }
        ]
    }
}

Here’s what I’ve tried:

json_file.json.lines | map(attribute='text') | join('\n') | from_json

or

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

json_file.json.lines | map(attribute='text') | join('\n') | to_json

After the join() (before from/to_json), the content looks something like this:

{\\n    \"AWS\": {\\n        \"S3\": {\\n            \"Bucket\": \"my-s3-bucket\"\\n            }\\n    }\\n  }

Neither of above filters return usable Json. As soon as I try to access an item in the Json I get VARIABLE IS UNDEFINED or I get Unexpected failure during module execution: Expecting property name enclosed in double quotes.

So how can I accomplish this?

>Solution :

I see two problems here.

Input is not valid JSON

If we extract the text in your example, we don’t get a valid JSON document. We get:

    "AWS": {"
        "S3": {"
            "Bucket": "my-s3-bucket"

That by itself is a fragment of a JSON document. In order to test out a solution, we would need minimally the equivlanet of:

{
    "AWS": {"
        "S3": {"
            "Bucket": "my-s3-bucket"
        }
    }
}

Filter does not result in valid JSON

When you write:

json_file.json.lines | map(attribute='text') | join('\n') | to_json

You are not joining lines with a newline. You are joining lines with the literal two-character sequence \n. That results in a document that is not valid JSON.

The simplest solution is just to join on "" instead.

The solution

Taking both of the above into account, we can put together something like this:

- hosts: localhost
  gather_facts: false
  vars:
    document: {
      "json": {
        "lines": [
              {
              "text": "{"
              },
              {
              "text": "    \"AWS\": {"
              },
              {
              "text": "        \"S3\": {"
              },
              {
              "text": "            \"Bucket\": \"my-s3-bucket\""
              },
              {
                "text": "}}}"
                }
          ]
      }
    }

  tasks:
    - set_fact:
        json: "{{ document.json.lines | map(attribute='text') | join('') }}"

    - debug:
        msg: "Bucket: {{ json.AWS.S3.Bucket }}"

Which produces as output:

PLAY [Testing] *****************************************************************

TASK [set_fact] ****************************************************************
ok: [localhost]

TASK [debug] *******************************************************************
ok: [localhost] => {
    "msg": "Bucket: my-s3-bucket"
}

PLAY RECAP *********************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading