com.scvngr.levelup.core.model.util.JsonUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.scvngr.levelup.core.model.util.JsonUtils.java

Source

/*
 * Copyright (C) 2014 SCVNGR, Inc. d/b/a LevelUp
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * 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.scvngr.levelup.core.model.util;

import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import com.scvngr.levelup.core.model.MonetaryValue;
import com.scvngr.levelup.core.util.IsoDateUtils;

import net.jcip.annotations.ThreadSafe;

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

import java.text.ParseException;
import java.util.Date;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import java.util.TimeZone;

/**
 * Helper class to work with {@link JSONObject} and avoid its bugs.
 * <http://code.google.com/p/android/issues/detail?id=13830>.
 */
@ThreadSafe
public final class JsonUtils {
    /**
     * Helper method that gets an optional nullable {@link Long} value from the {@link JSONObject}.
     *
     * @param json the {@link JSONObject}.
     * @param key the key in {@code json}.
     * @return {@link Long} mapping for {@code key} in {@code json} or {@code null} if no mapping
     *         exists.
     */
    @Nullable
    public static Long optLongNullable(@NonNull final JSONObject json, @NonNull final String key) {
        if (json.isNull(key)) {
            return null;
        }

        return json.optLong(key);
    }

    /**
     * Helper method that doesn't return some fake version of null if the string is null, it returns
     * null.
     *
     * @param json the {@link JSONObject}.
     * @param key the key in {@code json}.
     * @return {@link String} mapping for {@code key} in {@code json} or {@code null} if no mapping
     *         exists.
     */
    @Nullable
    public static String optString(@NonNull final JSONObject json, @NonNull final String key) {
        String value = null;

        if (!json.isNull(key)) {
            value = json.optString(key, null);
        }

        return value;
    }

    /**
     * Loads a {@link Date}.
     *
     * @param json the object to read from.
     * @param key the key in {@code json}.
     * @return A parsed {@link Date} or {@code null} if either the key is not present or is set to
     *         {@code null}.
     * @throws JSONException if the date could not be parsed.
     */
    @Nullable
    /* package */static Date optDate(@NonNull final JSONObject json, @NonNull final String key)
            throws JSONException {
        Date value = null;

        if (!json.isNull(key)) {
            try {
                value = IsoDateUtils.parseIsoDatetime(json.getString(key), TimeZone.getDefault());
            } catch (final ParseException e) {
                final JSONException jsonException = new JSONException("could not parse datetime");
                jsonException.initCause(e);
                throw jsonException;
            }
        }

        return value;
    }

    /**
     * Loads a {@link Set} of {@link Integer} from a {@link JSONArray} of integers.
     *
     * @param json the object to read from.
     * @param key the key in {@code json}.
     * @return a set of integers loaded from the array of integers at the given {@code key} or
     *         {@code null} if either the key is not present or is set to {@code null}.
     * @throws JSONException if the array contents aren't integers.
     */
    @Nullable
    public static Set<Integer> optIntegerSet(@NonNull final JSONObject json, @NonNull final String key)
            throws JSONException {
        Set<Integer> result = null;

        if (!json.isNull(key)) {
            final JSONArray array = json.optJSONArray(key);

            if (null != array) {
                final int count = array.length();
                result = new HashSet<Integer>(count);

                for (int i = 0; i < count; i++) {
                    result.add(array.getInt(i));
                }
            }
        }

        return result;
    }

    /**
     * Loads a {@link Set} of {@link String}s from a {@link JSONArray} of strings.
     *
     * @param json the object to read from.
     * @param key the key in {@code json}.
     * @return a set of strings loaded from the array of strings at the given {@code key} or
     *         {@code null} if either the key is not present or is set to {@code null}.
     * @throws JSONException if the array contents aren't strings.
     */
    @Nullable
    public static Set<String> optStringSet(@NonNull final JSONObject json, @NonNull final String key)
            throws JSONException {
        Set<String> result = null;

        if (!json.isNull(key)) {
            final JSONArray array = json.optJSONArray(key);

            if (null != array) {
                final int count = array.length();
                result = new HashSet<String>(count);

                for (int i = 0; i < count; i++) {
                    result.add(array.getString(i));
                }
            }
        }

        return result;
    }

    /**
     * Gets an optional {@link MonetaryValue} object from the JSON at the key passed.
     *
     * @param json the {@link JSONObject} to get the {@link MonetaryValue} from.
     * @param key the key in the {@link JSONObject} to get the {@link MonetaryValue} from.
     * @return a {@link MonetaryValue} from the parsed long or null.
     * @throws JSONException if the parsing fails.
     */
    @Nullable
    public static MonetaryValue optMonetaryValue(@NonNull final JSONObject json, @NonNull final String key)
            throws JSONException {
        final MonetaryValue value;
        final Long amount = json.optLong(key, Long.MIN_VALUE);

        if (Long.MIN_VALUE != amount) {
            value = new MonetaryValue(amount);
        } else {
            value = null;
        }

        return value;
    }

    /**
     * Gets a required {@link MonetaryValue} object from the JSON at the key passed or throws a
     * {@link JSONException} if it's missing.
     *
     * @param json the {@link JSONObject} to get the {@link MonetaryValue} from.
     * @param key the key in the {@link JSONObject} to get the {@link MonetaryValue} from.
     * @return a {@link MonetaryValue} from the parsed long.
     * @throws JSONException if the parsing fails.
     */
    @NonNull
    public static MonetaryValue getMonetaryValue(@NonNull final JSONObject json, @NonNull final String key)
            throws JSONException {
        final MonetaryValue value = optMonetaryValue(json, key);

        if (null == value) {
            throw new JSONException(String.format(Locale.US, "key %s is required.", key));
        }

        return value;
    }

    /**
     * Private constructor prevents instantiation.
     *
     * @throws UnsupportedOperationException because this class cannot be instantiated.
     */
    private JsonUtils() {
        throw new UnsupportedOperationException("This class is non-instantiable");
    }
}