/* ==================================================================
* JsonNodeUtils.java - 7/04/2017 8:31:02 PM
*
* Copyright 2017 SolarNetwork.net Dev Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
* ==================================================================
*/
package net.solarnetwork.util;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.JsonNode;
/**
* Utilities for parsing values from {@link JsonNode} objects.
*
* @author matt
* @version 1.0
* @since 1.35
*/
public class JsonNodeUtils {
private static final Logger LOG = LoggerFactory.getLogger(JsonNodeUtils.class);
/**
* Parse a BigDecimal from a JSON object attribute value.
*
* @param node
* the JSON node (e.g. object)
* @param key
* the attribute key to obtain from {@code node}
* @return the parsed {@link BigDecimal}, or <em>null</em> if an error
* occurs or the specified attribute {@code key} is not available
*/
public static BigDecimal parseBigDecimalAttribute(JsonNode node, String key) {
BigDecimal num = null;
if ( node != null ) {
JsonNode attrNode = node.get(key);
if ( attrNode != null && !attrNode.isNull() ) {
String txt = attrNode.asText();
if ( txt.indexOf('.') < 0 ) {
txt += ".0"; // force to decimal notation, so round-trip into samples doesn't result in int
}
try {
num = new BigDecimal(txt);
} catch ( NumberFormatException e ) {
LOG.debug("Error parsing decimal attribute [{}] value [{}]: {}",
new Object[] { key, attrNode, e.getMessage() });
}
}
}
return num;
}
/**
* Parse a Date from a JSON object attribute value.
*
* If the date cannot be parsed, <em>null</em> will be returned.
*
* @param node
* the JSON node (e.g. object)
* @param key
* the attribute key to obtain from {@code node}
* @param dateFormat
* the date format to use to parse the date string
* @return the parsed {@link Date} instance, or <em>null</em> if an error
* occurs or the specified attribute {@code key} is not available
*/
public static Date parseDateAttribute(JsonNode node, String key, DateFormat dateFormat) {
Date result = null;
if ( node != null ) {
JsonNode attrNode = node.get(key);
if ( attrNode != null && !attrNode.isNull() ) {
try {
String dateString = attrNode.asText();
// replace "midnight" with 12:00am
dateString = dateString.replaceAll("(?i)midnight", "12:00am");
// replace "noon" with 12:00pm
dateString = dateString.replaceAll("(?i)noon", "12:00pm");
result = dateFormat.parse(dateString);
} catch ( ParseException e ) {
LOG.debug("Error parsing date attribute [{}] value [{}] using pattern {}: {}",
new Object[] { key, attrNode,
(dateFormat instanceof SimpleDateFormat
? ((SimpleDateFormat) dateFormat).toPattern()
: dateFormat.toString()),
e.getMessage() });
}
}
}
return result;
}
/**
* Parse a Integer from a JSON object attribute value.
*
* If the Integer cannot be parsed, <em>null</em> will be returned.
*
* @param node
* the JSON node (e.g. object)
* @param key
* the attribute key to obtain from {@code node} node
* @return the parsed {@link Integer}, or <em>null</em> if an error occurs
* or the specified attribute {@code key} is not available
*/
public static Integer parseIntegerAttribute(JsonNode node, String key) {
Integer num = null;
if ( node != null ) {
JsonNode attrNode = node.get(key);
if ( attrNode != null && !attrNode.isNull() ) {
if ( attrNode.isIntegralNumber() ) {
num = attrNode.asInt();
} else {
String s = attrNode.asText();
if ( s != null ) {
s = s.trim();
}
try {
num = Integer.valueOf(s);
} catch ( NumberFormatException e ) {
LOG.debug("Error parsing integer attribute [{}] value [{}]: {}",
new Object[] { key, attrNode, e.getMessage() });
}
}
}
}
return num;
}
/**
* Parse a Long from a JSON object attribute value.
*
* If the Long cannot be parsed, <em>null</em> will be returned.
*
* @param node
* the JSON node (e.g. object)
* @param key
* the attribute key to obtain from {@code node} node
* @return the parsed {@link Long}, or <em>null</em> if an error occurs or
* the specified attribute {@code key} is not available
*/
public static Long parseLongAttribute(JsonNode node, String key) {
Long num = null;
if ( node != null ) {
JsonNode attrNode = node.get(key);
if ( attrNode != null && !attrNode.isNull() ) {
if ( attrNode.isIntegralNumber() ) {
num = attrNode.asLong();
} else {
try {
num = Long.valueOf(attrNode.asText());
} catch ( NumberFormatException e ) {
LOG.debug("Error parsing long attribute [{}] value [{}]: {}",
new Object[] { key, attrNode, e.getMessage() });
}
}
}
}
return num;
}
/**
* Parse a String from a JSON object attribute value.
*
* If the String cannot be parsed, <em>null</em> will be returned.
*
* @param node
* the JSON node (e.g. object)
* @param key
* the attribute key to obtain from {@code node} node
* @return the parsed {@link String}, or <em>null</em> if an error occurs or
* the specified attribute {@code key} is not available
*/
public static String parseStringAttribute(JsonNode node, String key) {
String s = null;
if ( node != null ) {
JsonNode attrNode = node.get(key);
if ( attrNode != null && !attrNode.isNull() ) {
s = attrNode.asText();
}
}
return s;
}
}