SFJsonObject

mail@pastecode.io avatar
unknown
plain_text
a month ago
11 kB
2
Indexable
Never
package com.nsi.storefront.service.coreapi.json;

import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.Option;
import com.nsi.storefront.service.coreapi.SFCoreAPIConstants;
import com.nsi.storefront.utils.SFLogger;
import com.nsi.storefront.utils.SFStringUtil;
import com.nsi.storefront.xmlschema.logging.types.LogEntryTypeEnum;
import net.minidev.json.JSONArray;
import org.json.JSONObject;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * ---------------- Copyright (c) 2020 Network Solutions, Inc. --------
 * THis class holds {@link JsonPath} related info and provides methods to access
 * <br>
 * <br>
 *
 * @author dbusireddy
 * @since 02-01-2020
 * -------------------------------------------------------------------
 */
public class SFJsonObject {
    private DocumentContext payloadObject;
    private Configuration pathConfiguration = Configuration.builder().options(Option.DEFAULT_PATH_LEAF_TO_NULL).build();
    private Map<String, String> fieldsAlreadyRetrieved = new HashMap<>();

    /**
     * @param jsonObject the {@link JSONObject}
     */
    public SFJsonObject(JSONObject jsonObject) {
        payloadObject = JsonPath.using(pathConfiguration).parse(jsonObject.toString());
    }

    /**
     * @param jsonString the JSON content
     */
    public SFJsonObject(String jsonString) {
        payloadObject = JsonPath.using(pathConfiguration).parse(jsonString);
    }

    /**
     * Returns field data for the given JSON path
     *
     * @param fieldPath the JSON path of the field
     * @return field data for the given JSON path
     */
    public String getField(String fieldPath) {
        String data = null;
        try {
            if (!fieldsAlreadyRetrieved.containsKey(fieldPath)) {
                String fieldValue = payloadObject.read(fieldPath, String.class);
                if (SFCoreAPIConstants.NULL_STRING.equalsIgnoreCase(fieldValue)) {
                    fieldValue = null;
                }
                fieldsAlreadyRetrieved.put(fieldPath, fieldValue);
            }
            data = fieldsAlreadyRetrieved.get(fieldPath);
        } catch (Exception exception) {
            // Ignore
        }
        return data;
    }

    /**
     * Returns number field data for the given JSON path
     * 
     * MBrown May 2021 - differentiating an error for an absent field vs
     * an invalid one.
     * 
     * Also relaxing the logging levels for errors in this
     * particular method - it is often called when null is a perfectly 
     * acceptable response, like:
     * 
     *   Integer startIndex = payLoad.getNumericField(SFCoreAPIConstants.START_INDEX_PATH) !=null ? 
     *       payLoad.getNumericField(SFCoreAPIConstants.START_INDEX_PATH) : SFCoreAPIConstants.ONE ;
     *
     * Since startIndex is an optional param for many SFCore APIs, it will often be 
     * absent from the JSON object, and we don't want to log an error for that.
     * 
     * @param fieldPath the JSON path of the field
     * @return number field data for the given JSON path
     */
    public Integer getNumericField(String fieldPath) {
        return getNumericField(fieldPath, null);
    }

    public Integer getNumericField(String fieldPath, Integer defaultValue) {
        Integer result = defaultValue;
        String numericData = getField(fieldPath);
        if (numericData == null ) {
            SFLogger.printDebug("SFJsonObject.getNumericField - field " + fieldPath
                    + " not found in JSON object.");
            return result;
        }
        try {
            result = Integer.parseInt(numericData);
        } catch (NumberFormatException exception) {
            SFLogger.printError(LogEntryTypeEnum.ERROR_MINOR_PROGRAM,
                    "Ignore this. SFJsonObject.getNumericField failed with invalid integer; "
                            + "field = " + fieldPath + ", data = " + numericData);
        }
        return result;
    }
    
    /**
     * Returns long field data for the given JSON path
     *
     * @param fieldPath the JSON path of the field
     * @return number field data for the given JSON path
     */
    public Long getLongField(String fieldPath) {
        Long result = null;
        try {
            result = Long.parseLong(getField(fieldPath));
        } catch (NumberFormatException exception) {
            // Ignore
        }
        return result;
    }


    /**
     * Returns boolean field data for the given JSON path
     *
     * @param fieldPath the JSON path of the field
     * @return boolean field data for the given JSON path
     */
    public boolean getBoolean(String fieldPath) {
        return Boolean.parseBoolean(getField(fieldPath));
    }



    /**
     * Returns jsonpath and respective field data for the given json paths as map
     *
     * @param pathList the list of json paths
     * @return jsonpath and respective field data
     */
    public Map<String, String> getFieldAndData(List<String> pathList) {
        Map<String, String> data = null;
        if (pathList != null && !pathList.isEmpty()) {
            data = new LinkedHashMap<>();
            for (String path : pathList) {
                data.put(getFieldNameByPath(path), getField(path));
            }
        }
        return data;
    }

    /**
     * The node data for the given JSON path
     *
     * @param nodePath the node path in JSON
     * @return the node data for the given JSON path
     */
    public Map getNode(String nodePath) {
        LinkedHashMap node = null;
        try {
            Object data = payloadObject.read(nodePath);
            if (data instanceof LinkedHashMap) {
                node = (LinkedHashMap) data;
            }

        } catch (Exception exception) {
            // Ignore
        }
        return node;
    }


    /**
     * The node data for the given JSON path
     *
     * @param nodePath the node path in JSON
     * @return the node data for the given JSON path
     */
    public List getMultipleFields(String nodePath) {
        List nodeValues = null;
        try {
            Object data = payloadObject.read(nodePath);
            if (data != null) {
                nodeValues = new ArrayList();
                if (data instanceof JSONArray) {
                    for (Object dataObj : ((JSONArray) data).toArray()) {
                        nodeValues.add(dataObj);
                    }
                } else if (data instanceof LinkedHashMap) {
                    nodeValues.addAll(((LinkedHashMap) data).keySet());
                } else {
                    nodeValues.add(data);
                }
            }
        } catch (Exception exception) {
            // Ignore
        }
        return nodeValues;
    }

    /**
     * The node data for the given JSON path
     *
     * @param nodePath the node path in JSON
     * @return the node data for the given JSON path
     */
    public Object[] getFieldArray(String nodePath) {
        List<Object> multipleFields = getMultipleFields(nodePath);
        return !CollectionUtils.isEmpty(multipleFields)?multipleFields.toArray():null;
    }

    /**
     * Returns the field name for the given json path
     *
     * @param aFieldPath the json filed path
     * @return the field name for the given json path
     */
    public static String getFieldNameByPath(String aFieldPath) {
        String result = null;
        if (aFieldPath != null) {
            if (aFieldPath.contains(SFCoreAPIConstants.DOT)) {
                String[] arr = aFieldPath.split(SFCoreAPIConstants.REG_EX_DOT);
                result = arr[arr.length - SFCoreAPIConstants.ONE];
            } else if (aFieldPath.contains((SFCoreAPIConstants.QUOTE))) {
                List<String> list = Arrays.asList(aFieldPath.split(SFCoreAPIConstants.QUOTE));
                if (list.size() >= SFCoreAPIConstants.TWO) {
                    result = list.get(list.size() - SFCoreAPIConstants.TWO);
                }
            }
        }
        return result;
    }

    /**
     * Returns true if the given json path contains multiple results path
     *
     * @param path the json path
     * @return true if the given json path contains multiple results path
     */
    public boolean isMultiple(String path) {
        Object data = null;
        try {
            data = payloadObject.read(path);
        } catch (Exception exception) {
            // Ignore
        }
        return path.contains(SFCoreAPIConstants.STAR)
                || data instanceof JSONArray || data instanceof LinkedHashMap;
    }

    /***
     * This method can be used to get a list of long values when the field holds a string of long values separated with comma.
     * eg. {"walletIds" : "1234567,12342345"}
     *
     * @param path
     * @return
     */
    public List<Long> getFieldLongList(String path){
        List<Long> longValuesList = null;
        try {
            String data = getField(path);
            if(!SFStringUtil.isEmpty(data)){
                longValuesList = new ArrayList<Long>();
                String[] dataArray = data.split(",");
                for(String dataStr : dataArray){
                    Long longValue = Long.parseLong(dataStr);
                    longValuesList.add(longValue);
                }
            }
        }catch (Exception e){
            SFLogger.printError(LogEntryTypeEnum.ERROR_MINOR_PROGRAM,
                    "Ignore this. SFJsonObject.getFieldLongList failed to read JSON path");
        }

        return longValuesList;
    }

    /***
     * This method can be used to get a list of String values when the field holds a string values separated with comma.
     * eg. {"productType" : "Domain,Email,Website"}
     *
     * @param path
     * @return
     */
    public List<String> getFieldStringList(String path){
        List<String> stringValuesList = null;
        try {
            String data = getField(path);
            if(!SFStringUtil.isEmpty(data)){
                stringValuesList = new ArrayList<String>();
                String[] dataArray = data.split(",");
                for(String dataStr : dataArray){
                    stringValuesList.add(dataStr);
                }
            }
        }catch (Exception e){
            SFLogger.printError(LogEntryTypeEnum.ERROR_MINOR_PROGRAM,
                    "Ignore this. SFJsonObject.getFieldStringList failed to read JSON path");
        }

        return stringValuesList;
    }
}