2

I am trying to get my attribute value from JSON data.

Here is my JSON data:

{
   "user1": "{\n \"data\":[\n    {\n     \"secure\": [\n       {\n              \"key\": \"-----BEGIN  KEY-----\nMIIEowIBAAKCAQEAgOh+Afb0oQEnvHifHuzBwhCP3\n-----END KEY-----\"\n       }\n      ],\n     \"owner\": \"shallake\",\n     \"position\": \"gl\"\n    }\n   ]\n}"
}

Initially, I had invalid JSON data, so I converted it into valid JSON using to_json and from_json. The above JSON data is the result that I get.

code:

 - set_fact:
      user: "{{ lookup('file','filepath/myfile.json') | to_json }}"

 - set_fact:
      user1: "{{ user | from_json}}"

 - set_fact:
      user3: "{{ item }}"
   with_items: "{{ user1['data'] | map(attribute='position') | list }}"

In a third set_fact, I am trying to get position attribute value. But it shows an error like this:

the field 'args' has an invalid value, which appears to include a variable that is undefined. The error was: 'item' is undefined

"\"{\n \\"data\\":[\n {\n \\"secure\\": [\n {\n \\"key\\": \\"-----BEGINPRIVATE KEY-----\nMIIEowIBAAKCAQEAgOh+Afb0oQEnvHifHuzBwl+Tiu8LXoJXb/ii/eh\ngYEP3\n-----END PRIVATE KEY-----\\"\n }\n ],\n \\"owner\\": \\"shalloke\\",\n \\"position\\": \\"gl\\"\n }\n ]\n}\n\n\""

So how can I get a position value from the above JSON data result using Ansible loop?

techraf
  • 64,883
  • 27
  • 193
  • 198
jake
  • 333
  • 1
  • 4
  • 12
  • its a result which i got from my code set_fact: user1: "{{ user | from_json }}" and iam try to get the "position" attribute value from the resultant of json data. – jake Sep 10 '16 at 05:47

2 Answers2

0

Would you please check if the key in filepath/myfile.json spans multiple lines? We need to escape line breaks in JSON. Use \n to replace line breaks.

The user1 is supported to be a map parsed from JSON. However, the JSON in filepath/myfile.json might be invalid. So in the second set_fact, this invalid JSON couldn't be parsed. Thus, user1 is just a string. And it doesn't contain an entry data.

{
  "data":[
      {
      "secure": [
        {
                "key": "-----BEGIN  KEY-----\nMIIEowIBAAKCAQEAgOh+Afb0oQEnvHifHuzBwhCP3\n-----END KEY-----"
        }
        ],
      "owner": "shallake",
      "position": "gl"
      }
    ]
}

How do I handle newlines in JSON?

Community
  • 1
  • 1
longhua
  • 4,142
  • 21
  • 28
  • I have tried that,now i convert my data as like this "\"{\\n \\\"data\\\":[\\n {\\n \\\"secure\\\": [\\n {\\n \\\"key\\\": \\\"-----BEGINPRIVATE KEY-----\\nMIIEowIBAAKCAQEAgOh+Afb0oQEnvHifHuzBwl+Tiu8LXoJXb/ii/eh\\ngYEP3\\n-----END PRIVATE KEY-----\\\"\\n }\\n ],\\n \\\"owner\\\": \\\"shalloke\\\",\\n \\\"position\\\": \\\"gl\\\"\\n }\\n ]\\n}\\n\\n\"" .I have checked ,its in a proper json format and type as dict.But how can i get "position" value from this item.I used with_items and get this as item in result.How can i get position valuein ansible – jake Sep 10 '16 at 20:58
  • @jake I am not sure what you want. You can get a list of position via `"{{ user2['data'] | map(attribute='position') | list }}"`. – longhua Sep 11 '16 at 01:53
  • I have given like this to get "position" attribute alone.But it shows like this FAILED! => {"failed": true, "msg": "the field 'args' has an invalid value, which appears to include a variable that is undefined. The error was: 'unicode object' has no attribute 'data'\ – jake Sep 11 '16 at 06:18
  • HoW tohandle USING ANSIBLE not with python Invalid control character at: line 6 column 61 (char 110) in ansible this error,Since i have space in my secure key values of json data. – jake Sep 11 '16 at 17:00
0

You should use either from_json (not to_json) filter, or not use filter at all, when importing file in a JSON format into an Ansible dictionary.

I point out the mistake below, but first a working example:

  • myfile.json:

    {
      "data": [
        {
          "secure": [
            {
              "key": "-----BEGIN  KEY-----\nMIIEowIBAAKCAQEAgOh+Afb0oQEnvHifHuzBwhCP3\n-----END KEY-----"
            }
          ],
          "owner": "shallake",
          "position": "gl"
        }
      ]
    }
    
  • Playbook:

    ---
    - hosts: localhost
      gather_facts: no
      connection: local
      tasks:
        - set_fact:
            data_from_json: "{{ lookup('file','./myfile.json') | from_json }}"
    
        - set_fact:
            position: "{{ item }}"
          with_items: "{{ data_from_json['data'] | map(attribute='position') | list }}"
    
        - name: Display extracted position
          debug:
            var: position
    
  • The result (relevant task only):

    TASK [Display extracted position] *********************************************************************************************************
    ok: [localhost] => {
        "position": "gl"
    }
    

Now your mistake:

Your myfile.json is not a correct JSON file.

You seemingly looked at the log of Ansible and copied it from the screen to the file. As you already saw, it will not be a valid JSON format (it will contain escaped quotes and newline characters which will prevent importing it).

If you want to copy the Ansible dictionary into a file, you can do it using the following task (I'm assuming here data is in the data_from_json variable, like at the end of my example playbook above):

- local_action: copy content={{ data_from_json | to_nice_json }} dest=./myfile2.json

to_nice_json is optional here, but it will produce very similar to the output as the myfile.json above (the order of keys might change and the indentation).

techraf
  • 64,883
  • 27
  • 193
  • 198