1

How to remove null and replace with a string novlaue?

I have below output stored in variable out1

{
    "out1": [
        [
            {
                "destination": "dest-a",
                "interface": "e1/1",
                "metric": "10",
                "name": "A"
            },
            {
                "destination": "dest-b",
                "interface": "e1/2",
                "metric": "10",
                "name": "B"
            },
            {
                "destination": "dest-c",
                "interface": null,
                "metric": "10",
                "name": "C"
            },
            {
                "destination": "dest-d",
                "interface": null,
                "metric": "10",
                "name": "B"
            }
        ]
    ]
}

I have a json_query in my code:

- debug: msg="{{out1 |json_query(myquery)}}"
  vars:
     myquery: "[].{dest: destination ,int: interface}"        
  register: out2

Above code will print the following:

{
    "msg": [
        {
            "dest": "dest-a",
            "int": "e1/1"
        },
        {
            "dest": "dest-b",
            "int": "e/12"
        },
        {
            "dest": "dest-c",
            "int": null
        },
        {
            "dest": "dest-d",
            "int": null
        }
    ]
}

I want to replace or remove null with the string novalue.

I looked into some posts and found default("novalue") can do the trick but in my case it is not working. I tried following added default("novalue") to my debug task, but I am getting an error.
I am sure that the error resides in myquery, the way I interpret/understand default() might be wrong and might be used wrongly.

Can anyone help me here please?

- debug: msg="{{out1 |json_query(myquery)}}"
  vars:
     myquery: "[].{dest: destination ,int: interface|default("novalue")}"        
  register: out2
β.εηοιτ.βε
  • 33,893
  • 13
  • 69
  • 83
netv
  • 165
  • 2
  • 12

3 Answers3

2

Otherwise, with another JMESPath expression to achieve this, you can use an or expression ||, that will display the value of interface or a string that you are free to define.

So, given your JSON:

[
    {
        "destination": "dest-a",
        "interface": "e1/1",
        "metric": "10",
        "name": "A"
    },
    {
        "destination": "dest-b",
        "interface": "e1/2",
        "metric": "10",
        "name": "B"
    },
    {
        "destination": "dest-c",
        "interface": null,
        "metric": "10",
        "name": "C"
    },
    {
        "destination": "dest-d",
        "interface": null,
        "metric": "10",
        "name": "B"
    }
]

And the JMESPath query

[].{dest: destination ,int: interface || 'novalue'}

This yields

[
  {
    "dest": "dest-a",
    "int": "e1/1"
  },
  {
    "dest": "dest-b",
    "int": "e1/2"
  },
  {
    "dest": "dest-c",
    "int": "novalue"
  },
  {
    "dest": "dest-d",
    "int": "novalue"
  }
]

And your task ends up being:

- debug: 
    msg: "{{ out1 | json_query(_query) }}"
  vars:
     _query: "[].{dest: destination ,int: interface || 'novalue')}"        
  register: out2
β.εηοιτ.βε
  • 33,893
  • 13
  • 69
  • 83
1

You are using the jinja2 default filter inside a jmespath (i.e. json_query) expression. This can't work.

You can use the jmespath function not_null in this case

The playbook:

---
- hosts: localhost
  gather_facts: false

  vars:
    "out1": [
      [
        {
          "destination": "dest-a",
          "interface": "e1/1",
          "metric": "10",
          "name": "A"
        },
        {
          "destination": "dest-b",
          "interface": "e1/2",
          "metric": "10",
          "name": "B"
        },
        {
          "destination": "dest-c",
          "interface": null,
          "metric": "10",
          "name": "C",
        },
        {
          "destination": "dest-d",
          "interface": null,
          "metric": "10",
          "name": "B"
        }
      ]
    ]

  tasks:
    - debug:
        msg: "{{ out1 | json_query(myquery) }}"
      vars:
        myquery: >-
          [].{dest: destination ,int: not_null(interface, 'no value')}

Gives:


PLAY [localhost] **************************************************************************************************************************************************************************************************************

TASK [debug] ******************************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        {
            "dest": "dest-a",
            "int": "e1/1"
        },
        {
            "dest": "dest-b",
            "int": "e1/2"
        },
        {
            "dest": "dest-c",
            "int": "no value"
        },
        {
            "dest": "dest-d",
            "int": "no value"
        }
    ]
}

PLAY RECAP ********************************************************************************************************************************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  
Zeitounator
  • 38,476
  • 7
  • 53
  • 66
0

Q: "How to remove 'null' and replace it with a string 'no value'?"

A: The variable out1 is a list of lists. Let's iterate it and create out2 with null replaced by 'no value' string. In each loop create the list of interface attributes with null replaced. Combine this list with the item and add it to the new list, e.g.

    - set_fact:
        out2: "{{ out2|d([]) + [item|zip(_item)|map('combine')] }}"
      loop: "{{ out1 }}"
      vars:
        _item: "{{ item|json_query(_query) }}"
        _query: |
          [].{interface: not_null(interface, 'no value')}

gives

  out2:
  - - destination: dest-a
      interface: e1/1
      metric: '10'
      name: A
    - destination: dest-b
      interface: e1/2
      metric: '10'
      name: B
    - destination: dest-c
      interface: no value
      metric: '10'
      name: C
    - destination: dest-d
      interface: no value
      metric: '10'
      name: B
Vladimir Botka
  • 58,131
  • 4
  • 32
  • 63