remove specified key from data container

40 views
Skip to first unread message

Michal Švamberg

unread,
Aug 12, 2021, 10:34:42 AM8/12/21
to help-cfengine
Hi all,
I like data containers with json. I have a simple data container

'{ "name1": "aaaa", "name2": "bbbb", "name3": "cccc" }'

and I don't know how to remove the key 'name2' from the data container.

I tried a difference function but its returns only slist, not data container. What is the best practice? Is posible using json_pipe, how?

Thanks
Michal Svamberg


Nick Anderson

unread,
Oct 14, 2021, 7:25:11 PM10/14/21
to help-c...@googlegroups.com

Hi Michal,

I can think of a couple ways of doing it. The first thing that came to mind was leveraging a classic array. This is a pattern that I have used for a long time. I still find it useful quite often. Another method that came to mind was to leverage jq via mapdata() using the json_pipe interpretation as you noted.

Here is an example:

bundle agent __main__
{
  vars:
      "original" data => '{ "name1": "aaaa", "name2": "bbbb", "name3": "cccc" }';

      # Method 0, build up a classic array using iteration
      "_original_keys" slist => getindices( original );
      "_a[$(_original_keys)]"
        string => "$(original[$(_original_keys)])",
        unless => strcmp( "name2", "$(_original_keys)" );
      "method_0" data => mergedata( "_a" );

      # Method 1, jq via json_pipe
      # mapdata returns a json array, so we use parsejson(nth(0)) to pick out the dict
      "_method_1_json_array"
        data => mapdata( "json_pipe",
                         `$(def.jq) 'del(.name2)'`,
                         original);
      "method_1" data => mergedata( "_method_1_json_array[0]" );
}
# cf-agent --no-lock --log-level info --show-evaluated-vars=default:main\\. --file /tmp/example.cf
Variable name                            Variable value                                               Meta tags                                Comment                                 
default:main._a[name1]                   aaaa                                                         source=promise                                                                   
default:main._a[name3]                   cccc                                                         source=promise                                                                   
default:main._method_1_json_array        [{"name1":"aaaa","name3":"cccc"}]                            source=promise                                                                   
default:main._original_keys               {"name1","name2","name3"}                                   source=promise                                                                   
default:main.method_0                    {"name1":"aaaa","name3":"cccc"}                              source=promise                                                                   
default:main.method_1                    {"name1":"aaaa","name3":"cccc"}                              source=promise                                                                   
default:main.original                    {"name1":"aaaa","name2":"bbbb","name3":"cccc"}               source=promise                                                                   

I don't know that I have any firm position on what is best. I think both methodologies have their own merits. The classic array generator works anywhere CFEngine works. mapdata() using the json_pipe interpretationrequires some external utility like jq which may not be universally available.

Hope this helps …

Don't forget to check out our "The Agent is In" series on YouTube. Smash that like button, subscribe, ring that bell so you get notified of anything new, become a member … oh, well okay we don't have YouTube memberships yet I guess.

Reply all
Reply to author
Forward
0 new messages