Gson's missing get element function - Part I



The Gson missing recursive get function.

One of the issues with the current get function that is available is that it only search’s top-level entry key for the value that is passed in.

Example
JsonObject result; // json object for the preview below

If a result.get(“username”) is done the following set will return null because as I have said above the inbuilt get function only search top level element you wish to find.

The following values exists in the top-level [“result”, “error”, “id”] the inner elements will not be searched which is part of the flaw / weakness of using the in-built method. A solution to this problem is show below:

{
    "result" : {
        "total_items" : 1,
        "total_pages" : 1,
        "items_per_page" : 25,
        "current_page" : 1,
        "items" : [{
                "username" : "test",
                "apikey" : "12345",
                "secret" : "",
                "application" : {
                    "name" : "test app"
                }
            }
        ]
    },
    "error" : null,
    "id" : 1
}



import java.util.Map.Entry;
import java.util.Set;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;


public class GsonUtil {

    /**
     * The following function does a top-down recursive descent on a json tree to
     * find an element with-in structure
     *
     * @param value : value to retrieve
     * @param jObj : json object to traverse
     * @return JsonElement if found or null if element not found
     */
    public static JsonElement get(String value, JsonObject jObj) {

        // check current level for the key before descending
        if (jObj.isJsonObject() && jObj.has(value)) {
            return jObj.get(value);
        }

        // get all entry sets
        Set<Entry<String, JsonElement>> entries = jObj.entrySet();
       
        for (Entry<String, JsonElement> entry : entries) {
           
            // cache the current value since retrieval is done so much
            JsonElement curVal = entry.getValue();
           
            if (curVal.isJsonArray()) {
                for (JsonElement el : curVal.getAsJsonArray()) {
                    // recursively traverse the sub-tree
                    JsonElement res = get(value, el.getAsJsonObject());
                    if (res != null)
                        return res;
                }
            } else if (curVal.isJsonObject()) {
                // traverse sub-node
                return get(value, curVal.getAsJsonObject());
            }
        }
        return null;
    }
   
}

The above method solves the short-comings of the in-built get method. The above method is a recursive get method that iterates over the json object (tree) entryset recursively searching all branches until the element has been found. In the above method, whenever an element (primitive element) is discovered that corresponding JsonElement is returned if the value is not found, a further check is done to determine if the element is an array; if the element is an array a traversal is done on the array to find the value, passing in the array object item. 


If the value being traversed is a JsonObject a recursive search is done on its inner elements to determine of the value being searched exists. If the value is not found null is returned
NB: Top-levels values are searched first then a descent is done on inner elements (performance boost)

Comments

Popular posts from this blog

JavaScript Module Pattern: 2 Forms

Pseudo-Random UUID Generation with mask support

Mocking Ajax with the JQuery Mockjax Library