Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find a particular JSON value by key?

There is a JSON like this:

{   "P1": "ss",   "Id": 1234,   "P2": {       "P1": "cccc"   },   "P3": [       {           "P1": "aaa"       }   ] } 

How can I find all P1's value without it iterating all JSON?

P.S.: P1 can be anywhere in the JSON.

If no method can do this, can you tell me how to iterate through the JSON?

like image 863
lichengwu Avatar asked Dec 27 '12 03:12

lichengwu


People also ask

How can I get specific data from JSON?

Getting a specific property from a JSON response object Instead, you select the exact property you want and pull that out through dot notation. The dot ( . ) after response (the name of the JSON payload, as defined arbitrarily in the jQuery AJAX function) is how you access the values you want from the JSON object.

How can I get the key-value in a JSON object?

To get a JSON object's key and value in JavaScript, we can use the JSON. parse method to parse the JSON object string into a JavaScript object. Then we can get a property's value as we do with any other JavaScript object.

How do you check if a JSON object contains a key or not?

Use below code to find key is exist or not in JsonObject . has("key") method is used to find keys in JsonObject . If you are using optString("key") method to get String value then don't worry about keys are existing or not in the JsonObject . Note that you can check only root keys with has(). Get values with get().


2 Answers

As I said in my other answer, I don't think there is a way of finding all values associated with the "P1" key without iterating over the whole structure. However I've come up with even better way to do that which came to me while looking at @Mike Brennan's answer to another JSON-related question How to get string objects instead of Unicode from JSON?

The basic idea is to use the object_hook parameter that json.loads() accepts just to watch what is being decoded and check for the sought-after value.

Note: This will only work if the representation is of a JSON object (i.e. something enclosed in curly braces {}), as in your sample.

from __future__ import print_function import json  def find_values(id, json_repr):     results = []      def _decode_dict(a_dict):         try:             results.append(a_dict[id])         except KeyError:             pass         return a_dict      json.loads(json_repr, object_hook=_decode_dict) # Return value ignored.     return results  json_repr = '{"P1": "ss", "Id": 1234, "P2": {"P1": "cccc"}, "P3": [{"P1": "aaa"}]}' print(find_values('P1', json_repr)) 

(Python 3) output:

['cccc', 'aaa', 'ss'] 
like image 94
martineau Avatar answered Sep 22 '22 17:09

martineau


I had the same issue just the other day. I wound up just searching through the entire object and accounted for both lists and dicts. The following snippets allows you to search for the first occurrence of a multiple keys.

import json  def deep_search(needles, haystack):     found = {}     if type(needles) != type([]):         needles = [needles]      if type(haystack) == type(dict()):         for needle in needles:             if needle in haystack.keys():                 found[needle] = haystack[needle]             elif len(haystack.keys()) > 0:                 for key in haystack.keys():                     result = deep_search(needle, haystack[key])                     if result:                         for k, v in result.items():                             found[k] = v     elif type(haystack) == type([]):         for node in haystack:             result = deep_search(needles, node)             if result:                 for k, v in result.items():                     found[k] = v     return found  deep_search(["P1", "P3"], json.loads(json_string)) 

It returns a dict with the keys being the keys searched for. Haystack is expected to be a Python object already, so you have to do json.loads before passing it to deep_search.

Any comments for optimization are welcomed!

like image 39
Sean Linehan Avatar answered Sep 23 '22 17:09

Sean Linehan