Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

search json for key with particular value

by rahulruns (Scribe)
on Dec 15, 2020 at 14:00 UTC ( #11125231=perlquestion: print w/replies, xml ) Need Help??

rahulruns has asked for the wisdom of the Perl Monks concerning the following question:

In a json if I want to search for a key which could be at any level and multiple places, how do I do it. Example I have below JSON. In JSON there are places where componentID is present. Each ComponentId is different. I need to search value of that componentId in json and where it matches pick that object in json. This is kind of function which helps to pickup that object out of json based on componentId value. Any module to achieve this or any idea to help on this

json "infra": { "config": { "rack": [ { "componentId": "xxx-001", "model": "xxx", "server": [ { "componentId": "server-001", "type": "xxxx", "model": "xxxx", "role": "Management", "specificAttributes": "" ............ "platform": { "config": { "mgmtser": [{ "componentId": "sr-001", "domainName": "xxxxx", "thinDiskMode": true, "deployment": "small",

Replies are listed 'Best First'.
Re: search json for key with particular value
by hippo (Chancellor) on Dec 15, 2020 at 15:25 UTC

    Sounds like a job for Data::DPath:

    #!/usr/bin/env perl use strict; use warnings; use JSON::MaybeXS; use Data::DPath 'dpath'; use Data::Dumper; my $json = <<EOT; { "infra": { "config": { "rack": [ { "componentId": "xxx-001", "model": "xxx", "server": [ { "componentId": "server-001", "type": "xxxx", "model": "xxxx", "role": "Management", "specificAttributes": "" } ] }] }, "platform": { "config": { "mgmtser": [{ "componentId": "sr-001", "domainName": "xxxxx", "thinDiskMode": true, "deployment": "small" } ]} } } } EOT my $data = decode_json ($json); my @res = dpath ('//*[ key eq "componentId"]/..')->match ($data); print Dumper (\@res);

    🦛

Re: search json for key with particular value
by pryrt (Monsignor) on Dec 15, 2020 at 14:46 UTC
    The way I would approach the task is to recurse into each object, and return the current object if it has a "componentId" key whose value matches your restriction.

    Here is some code that does the recursion and returns all objects that include a "componentId". I marked the line where you would edit the logic to only return objects that have componentId whose value matches.

    I am not a JSON expert, so there may be a way using the JSON module or helper module to do a more efficient recursive search than my manual answer. I yield to wiser monks.

    --

    edit: JSON module will be faster if you have installed JSON::XS, because it will try to use that if possible.

    edit2: updated code to use the OP-style data, as interpreted by hippo, rather than my proprietary data; also fixed post and code so "componentId" had correct case on the "d"

      Thank you for your answer I was thinking of recursing structure but was looking if there is any other possibility except recursing structure

[OT} Re: search json for key with particular value
by erix (Parson) on Dec 17, 2020 at 13:23 UTC

    Not a perl answer, and probably not even useful for the OP, unless the JSON is large/many, and a database is at hand.

    Nevertheless, and Just For Fun: indexed JSON in PostgreSQL:

    --> show rowcount of the test table: db=# select count(*) from myjsonfile100k ; count -------- 790000 (1 row) --> show size of the test table, and index: db=# \dti+ myjsonfile100k* List of relatio +ns Schema | Name | Type | Owner | T +able | Persistence | Size | Description --------+-----------------------------------+-------+----------+------ +----------+-------------+--------+----------------------- public | myjsonfile100k | table | aardvark | + | permanent | 589 MB | public | myjsonfile100k_js_pathops_gin_idx | index | aardvark | myjso +nfile100k | permanent | 135 MB | public | myjsonfile100k_pkey | index | aardvark | myjso +nfile100k | permanent | 17 MB | (3 rows) --> show table+index structure db=# \d+ myjsonfile100k Table "public.myjsonfi +le100k" Column | Type | Collation | Nullable | Default + | Storage | Stats target | Description --------+---------+-----------+----------+---------------------------- +----------------+----------+--------------+------------- js | jsonb | | | + | extended | | id | integer | | not null | nextval('myjsonfile100k_id_ +seq'::regclass) | plain | | Indexes: "myjsonfile100k_pkey" PRIMARY KEY, btree (id) "myjsonfile100k_js_pathops_gin_idx" gin (js jsonb_path_ops) Access method: heap --> show single jsonb 'record' structure: db=# select jsonb_pretty(js) from myjsonfile100k limit 1; jsonb_pretty + ---------------------------------------------------------------------- +--------------------------------- { + + "bool": false, + + "city": "Cebu City", + + "date": "1980-08-12", + + "enum": "generator", + + "array": [ + + "Eve", + + "Chandra", + + "Binny", + + "Tabbatha", + + "Anallese" + + ], + + "regEx": "hellooooooooooooooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooo to you",+ "random": 11, + + "country": "Iran, Islamic Republic Of", + + "lastname": "Seligman", + + "firstname": "Correy", + + "countryCode": "DE", + + "random float": 60.823, + + "array of objects": [ + + { + + "index": 0, + + "index start at 5": 5 + + }, + + { + + "index": 1, + + "index start at 5": 6 + + }, + + { + + "index": 2, + + "index start at 5": 7 + + } + + ], + + "email from expression": "Correy.Seligman@yopmail.com", + + "email uses current data": "Correy.Seligman@gmail.com" + + } (1 row) --> crunch time: --> (NOTE that below I truncated the result rows with '...' for PM +-display): db=# select id , js->>'firstname' as fname , js->>'lastname' as lname , * from myjsonfile100k where js @> '{"firstname": "Lilith"}' -- nevermind the crazy names, and js @> '{"lastname": "Trace"}' -- randomly generated stuff ; id | fname | lname | + + --------+--------+-------+-------------------------------------------- +---------------------- 127245 | Lilith | Trace | {"bool": false, "city": "Kolkata", "date": +"1995-05-14", "enum": ... 393835 | Lilith | Trace | {"bool": true, "city": "Sarajevo", "date": +"1987-06-07", "enum": ... (2 rows) Time: 0.846 ms --> less than a millisecond

    All this is in released PostgreSQL, i.e., postgres 13.

    But JSON indexing in postgres is still an area of intensive development - more JSON flexibility is in the dev pipeline)

    (TWIMC, for future tech detail (rather low-level): http://www.sai.msu.su/~megera/postgres/talks/json-build-2020.pdf )

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://11125231]
Approved by LanX
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (6)
As of 2021-02-24 21:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?