com.amazon.android.utils.JsonHelper.java Source code

Java tutorial

Introduction

Here is the source code for com.amazon.android.utils.JsonHelper.java

Source

/**
 * Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *     http://aws.amazon.com/apache2.0/
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */
package com.amazon.android.utils;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * This is a helper class that parses a JSON-encoded string into a Map. This class uses
 * JSONObject and JSONArray from org.json to handle the JSON manipulation.
 */
public class JsonHelper {

    private static final String TAG = JsonHelper.class.getSimpleName();

    /**
     * Comment start sequence.
     */
    private static final String COMMENT_START_SEQUENCE_ESCAPED = "\\/\\*";

    /**
     * Comment stop sequence.
     */
    private static final String COMMENT_STOP_SEQUENCE_ESCAPED = "\\*\\/";

    /**
     * Turns a Map object into a JSON-encoded string. Uses the JSONObject from org.json to create
     * the string.
     *
     * @param map The Map to convert.
     * @return A JSON-encoded String that represents the map parameter.
     */
    public static String mapToString(Map<String, Object> map) {

        if (map == null) {
            return null;
        }

        JSONObject object = new JSONObject(map);
        return object.toString();
    }

    /**
     * Parses a JSON-encoded string into a Map. If the data string is malformed
     * in any way, an exception is thrown.
     *
     * @param data The JSON-encoded string.
     * @return A Map containing the parsed JSON pairs of the string. If the data string is null or
     * empty, this method returns an empty map.
     * @throws Exception if the JSON-encoded string is malformed.
     */
    public static Map stringToMap(String data) throws Exception {

        JSONObject jsonObject;

        // Return an empty map for null or empty data string.
        if (data == null || data.isEmpty()) {
            return parseObject(null);
        }

        try {
            // Create a JSONObject from the data string.
            jsonObject = new JSONObject(data);

        } catch (JSONException e) {

            Log.e(TAG, "Error creating JSON Object from string.", e);
            throw new MalformedJSONException("Malformed JSON-encoded string", e);
        }
        // Parse the object and return its map representation.
        return parseObject(jsonObject);
    }

    /**
     * Helper method to parse a JSONObject.
     *
     * @param object The JSONObject to parse.
     * @return A Map containing the key/value pairs of the JSONObject. If the object passed in is
     * null, an empty map is returned.
     * @throws Exception if the JSON-encoded object is malformed.
     */
    private static Map parseObject(JSONObject object) throws Exception {

        LinkedHashMap<String, Object> map = new LinkedHashMap<>();

        if (object != null) {

            Iterator<String> keys = object.keys();

            // Loop through all keys
            while (keys.hasNext()) {

                String key = keys.next();

                try {
                    // Parse the value associated with the key and add it to the map.
                    map.put(key, parseValue(object.get(key)));

                } catch (JSONException e) {

                    Log.e(TAG, "Invalid key-value mapping for key: " + key, e);
                    throw new MalformedJSONException("Malformed JSON. Contains a bad key: " + key, e);
                }
            }
        }
        return map;
    }

    /**
     * Helper method to parse a JSONArray.
     *
     * @param array The JSONArray to parse.
     * @return A List of the Objects from the JSONArray. If the array passed in is null, an empty
     * ArrayList is returned.
     * @throws Exception if the JSON-encoded array is malformed.
     */
    private static List parseArray(JSONArray array) throws Exception {

        ArrayList<Object> list = new ArrayList<>();

        if (array != null) {

            // Parse each value in the array and add it to the list.
            for (int i = 0; i < array.length(); i++) {

                try {

                    list.add(parseValue(array.get(i)));

                } catch (JSONException e) {
                    Log.e(TAG, "Array contains no value at index: " + i, e);
                    throw new MalformedJSONException("Malformed JSON. Array contains no value at " + "index: " + i,
                            e);
                }

            }
        }
        return list;
    }

    /**
     * Helper method to parse a value.
     *
     * @param value The value to parse.
     * @return An Object that represents the parsed object.
     * @throws Exception if the JSON-encoded value is malformed.
     */
    private static Object parseValue(Object value) throws Exception {

        // If value is a JSONObject, parse the JSONObject
        if (value instanceof JSONObject) {
            return parseObject((JSONObject) value);
        }
        // If value is a JSONArray, parse the JSONArray
        else if (value instanceof JSONArray) {
            return parseArray((JSONArray) value);
        }
        // Otherwise the value is an Object, String, int, etc, so just return its value.
        return value;
    }

    /**
     * This method removes comments from JSON string.
     *
     * @param jsonString JSON string with comments.
     * @return JSON string without comments.
     */
    public static String escapeComments(String jsonString) {

        if (jsonString == null) {
            return null;
        }

        String regex = COMMENT_START_SEQUENCE_ESCAPED + "(.*?|\n)" + // Match all type of cases including new line.
                COMMENT_STOP_SEQUENCE_ESCAPED;

        StringBuffer stringBuffer = new StringBuffer(jsonString.length());
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(jsonString);
        while (matcher.find()) {
            matcher.appendReplacement(stringBuffer, "");
        }
        matcher.appendTail(stringBuffer);

        return stringBuffer.toString();
    }

    /**
     * An exception class to for malformed strings.
     */
    public static class MalformedJSONException extends Exception {

        /**
         * Constructor for the exception.
         *
         * @param message The custom message to display.
         * @param e       The throwable exception that took place.
         */
        public MalformedJSONException(String message, Throwable e) {

            super(message, e);
        }
    }
}