Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.text.StringCharacterIterator;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
Expand All @@ -60,23 +69,22 @@ public class DefaultJSONWriter implements JSONWriter {

private static final Logger LOG = LogManager.getLogger(DefaultJSONWriter.class);

private static char[] hex = "0123456789ABCDEF".toCharArray();
private static final char[] hex = "0123456789ABCDEF".toCharArray();

private static final ConcurrentMap<Class<?>, BeanInfo> BEAN_INFO_CACHE_IGNORE_HIERARCHY = new ConcurrentHashMap<>();
private static final ConcurrentMap<Class<?>, BeanInfo> BEAN_INFO_CACHE = new ConcurrentHashMap<>();

private StringBuilder buf = new StringBuilder();
private final StringBuilder buf = new StringBuilder();
private Stack<Object> stack = new Stack<>();
private boolean ignoreHierarchy = true;
private Object root;
private boolean buildExpr = true;
private String exprStack = "";
private Collection<Pattern> excludeProperties;
private Collection<Pattern> includeProperties;
private DateFormat formatter;
private DateFormat dateFormatter;
private boolean enumAsBean = ENUM_AS_BEAN_DEFAULT;
private boolean excludeNullProperties;
private boolean cacheBeanInfo = true;
private boolean excludeProxyProperties;

@Inject(value = JSONConstants.RESULT_EXCLUDE_PROXY_PROPERTIES, required = false)
Expand All @@ -95,14 +103,10 @@ public String write(Object object) throws JSONException {
}

/**
* @param object
* Object to be serialized into JSON
* @param excludeProperties
* Patterns matching properties to ignore
* @param includeProperties
* Patterns matching properties to include
* @param excludeNullProperties
* enable/disable excluding of null properties
* @param object Object to be serialized into JSON
* @param excludeProperties Patterns matching properties to ignore
* @param includeProperties Patterns matching properties to include
* @param excludeNullProperties enable/disable excluding of null properties
* @return JSON string for object
* @throws JSONException in case of error during serialize
*/
Expand All @@ -128,7 +132,6 @@ public String write(Object object, Collection<Pattern> excludeProperties,
*
* @param object Object to be serialized into JSON
* @param method method
*
* @throws JSONException in case of error during serialize
*/
protected void value(Object object, Method method) throws JSONException {
Expand Down Expand Up @@ -159,8 +162,7 @@ protected void value(Object object, Method method) throws JSONException {
*
* @param object Object to be serialized into JSON
* @param method method
*
* @throws JSONException in case of error during serialize
* @throws JSONException in case of error during serialize
*/
protected void process(Object object, Method method) throws JSONException {
this.stack.push(object);
Expand All @@ -185,6 +187,8 @@ protected void process(Object object, Method method) throws JSONException {
this.date((Date) object, method);
} else if (object instanceof Calendar) {
this.date(((Calendar) object).getTime(), method);
} else if (object instanceof TemporalAccessor) {
this.temporal((TemporalAccessor) object, method);
} else if (object instanceof Locale) {
this.string(object);
} else if (object instanceof Enum) {
Expand All @@ -201,8 +205,7 @@ protected void process(Object object, Method method) throws JSONException {
*
* @param object object
* @param method method
*
* @throws JSONException in case of error during serialize
* @throws JSONException in case of error during serialize
*/
protected void processCustom(Object object, Method method) throws JSONException {
this.bean(object);
Expand All @@ -212,8 +215,7 @@ protected void processCustom(Object object, Method method) throws JSONException
* Instrospect bean and serialize its properties
*
* @param object object
*
* @throws JSONException in case of error during serialize
* @throws JSONException in case of error during serialize
*/
protected void bean(Object object) throws JSONException {
this.add("{");
Expand Down Expand Up @@ -334,23 +336,22 @@ protected Method findBaseAccessor(Class clazz, Method accessor) {
} else if (clazz.getName().contains("$$_javassist")) {
try {
baseAccessor = Class.forName(
clazz.getName().substring(0, clazz.getName().indexOf("_$$")))
clazz.getName().substring(0, clazz.getName().indexOf("_$$")))
.getMethod(accessor.getName(), accessor.getParameterTypes());
} catch (Exception ex) {
LOG.debug(ex.getMessage(), ex);
}
//in hibernate4.3.7,because javassist3.18.1's class name generate rule is '_$$_jvst'+...
} else if(clazz.getName().contains("$$_jvst")){

//in hibernate4.3.7,because javassist3.18.1's class name generate rule is '_$$_jvst'+...
} else if (clazz.getName().contains("$$_jvst")) {
try {
baseAccessor = Class.forName(
clazz.getName().substring(0, clazz.getName().indexOf("_$$")))
clazz.getName().substring(0, clazz.getName().indexOf("_$$")))
.getMethod(accessor.getName(), accessor.getParameterTypes());
} catch (Exception ex) {
LOG.debug(ex.getMessage(), ex);
}
}
else {
} else {
return accessor;
}
return baseAccessor;
Expand All @@ -361,8 +362,7 @@ protected Method findBaseAccessor(Class clazz, Method accessor) {
* including all its own properties
*
* @param enumeration the enum
*
* @throws JSONException in case of error during serialize
* @throws JSONException in case of error during serialize
*/
protected void enumeration(Enum enumeration) throws JSONException {
if (enumAsBean) {
Expand All @@ -385,7 +385,7 @@ protected String expandExpr(int i) {
}

protected String expandExpr(String property) {
if (this.exprStack.length() == 0) {
if (this.exprStack.isEmpty()) {
return property;
}
return this.exprStack + "." + property;
Expand All @@ -401,9 +401,7 @@ protected boolean shouldExcludeProperty(String expr) {
if (this.excludeProperties != null) {
for (Pattern pattern : this.excludeProperties) {
if (pattern.matcher(expr).matches()) {
if (LOG.isDebugEnabled()) {
LOG.debug("Ignoring property because of exclude rule: " + expr);
}
LOG.debug("Ignoring property because of exclude rule: {}", expr);
return true;
}
}
Expand All @@ -415,9 +413,7 @@ protected boolean shouldExcludeProperty(String expr) {
return false;
}
}
if (LOG.isDebugEnabled()){
LOG.debug("Ignoring property because of include rule: " + expr);
}
LOG.debug("Ignoring property because of include rule: {}", expr);
return true;
}
return false;
Expand Down Expand Up @@ -498,14 +494,52 @@ protected void date(Date date, Method method) {
JSON json = null;
if (method != null)
json = method.getAnnotation(JSON.class);
if (this.formatter == null)
this.formatter = new SimpleDateFormat(JSONUtil.RFC3339_FORMAT);
if (this.dateFormatter == null)
this.dateFormatter = new SimpleDateFormat(JSONUtil.RFC3339_FORMAT);

DateFormat formatter = (json != null) && (json.format().length() > 0) ? new SimpleDateFormat(json
.format()) : this.formatter;
.format()) : this.dateFormatter;
this.string(formatter.format(date));
}

/*
* Add temporal (java.time) value to buffer
*/
protected void temporal(TemporalAccessor temporal, Method method) {
JSON json = null;
if (method != null) {
json = method.getAnnotation(JSON.class);
}

DateTimeFormatter formatter;
if (json != null && json.format().length() > 0) {
formatter = DateTimeFormatter.ofPattern(json.format());
if (temporal instanceof Instant) {
formatter = formatter.withZone(ZoneOffset.UTC);
}
} else {
formatter = getDefaultDateTimeFormatter(temporal);
}
this.string(formatter.format(temporal));
}

private DateTimeFormatter getDefaultDateTimeFormatter(TemporalAccessor temporal) {
if (temporal instanceof LocalDate) {
return DateTimeFormatter.ISO_LOCAL_DATE;
} else if (temporal instanceof LocalDateTime) {
return DateTimeFormatter.ISO_LOCAL_DATE_TIME;
} else if (temporal instanceof LocalTime) {
return DateTimeFormatter.ISO_LOCAL_TIME;
} else if (temporal instanceof ZonedDateTime) {
return DateTimeFormatter.ISO_ZONED_DATE_TIME;
} else if (temporal instanceof OffsetDateTime) {
return DateTimeFormatter.ISO_OFFSET_DATE_TIME;
} else if (temporal instanceof Instant) {
return DateTimeFormatter.ISO_INSTANT;
}
return DateTimeFormatter.ISO_DATE_TIME;
}

/*
* Add array to buffer
*/
Expand Down Expand Up @@ -664,13 +698,13 @@ public void setEnumAsBean(boolean enumAsBean) {
@Override
public void setDateFormatter(String defaultDateFormat) {
if (defaultDateFormat != null) {
this.formatter = new SimpleDateFormat(defaultDateFormat);
this.dateFormatter = new SimpleDateFormat(defaultDateFormat);
}
}

@Override
public void setCacheBeanInfo(boolean cacheBeanInfo) {
this.cacheBeanInfo = cacheBeanInfo;
// no-op
}

@Override
Expand Down Expand Up @@ -699,7 +733,7 @@ public String getName() {
public JSONAnnotationFinder invoke() {
JSON json = accessor.getAnnotation(JSON.class);
serialize = json.serialize();
if (serialize && json.name().length() > 0) {
if (serialize && !json.name().isEmpty()) {
name = json.name();
}
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalQuery;
import java.util.*;

/**
Expand Down Expand Up @@ -132,7 +141,11 @@ private static boolean isJSONPrimitive(Class clazz) {
|| clazz.equals(Boolean.class) || clazz.equals(Byte.class) || clazz.equals(Character.class)
|| clazz.equals(Double.class) || clazz.equals(Float.class) || clazz.equals(Integer.class)
|| clazz.equals(Long.class) || clazz.equals(Short.class) || clazz.equals(Locale.class)
|| clazz.isEnum();
|| clazz.isEnum()
|| Calendar.class.isAssignableFrom(clazz)
|| clazz.equals(LocalDate.class) || clazz.equals(LocalDateTime.class)
|| clazz.equals(LocalTime.class) || clazz.equals(ZonedDateTime.class)
|| clazz.equals(OffsetDateTime.class) || clazz.equals(Instant.class);
}

@SuppressWarnings("unchecked")
Expand Down Expand Up @@ -367,6 +380,32 @@ else if (String.class.equals(clazz))
LOG.error("Unable to parse date from: {}", value, e);
throw new JSONException("Unable to parse date from: " + value);
}
} else if (Calendar.class.isAssignableFrom(clazz)) {
try {
JSON json = method.getAnnotation(JSON.class);

DateFormat formatter = new SimpleDateFormat(
(json != null) && (json.format().length() > 0) ? json.format() : this.dateFormat);
Date date = formatter.parse((String) value);
Calendar cal = Calendar.getInstance();
cal.setTime(date);
return cal;
} catch (ParseException e) {
LOG.error("Unable to parse calendar from: {}", value, e);
throw new JSONException("Unable to parse calendar from: " + value);
}
} else if (clazz.equals(LocalDate.class)) {
return parseTemporalFromString(value, method, DateTimeFormatter.ISO_LOCAL_DATE, LocalDate::from);
} else if (clazz.equals(LocalDateTime.class)) {
return parseTemporalFromString(value, method, DateTimeFormatter.ISO_LOCAL_DATE_TIME, LocalDateTime::from);
} else if (clazz.equals(LocalTime.class)) {
return parseTemporalFromString(value, method, DateTimeFormatter.ISO_LOCAL_TIME, LocalTime::from);
} else if (clazz.equals(ZonedDateTime.class)) {
return parseTemporalFromString(value, method, DateTimeFormatter.ISO_ZONED_DATE_TIME, ZonedDateTime::from);
} else if (clazz.equals(OffsetDateTime.class)) {
return parseTemporalFromString(value, method, DateTimeFormatter.ISO_OFFSET_DATE_TIME, OffsetDateTime::from);
} else if (clazz.equals(Instant.class)) {
return parseInstantFromString(value, method);
} else if (clazz.isEnum()) {
String sValue = (String) value;
return Enum.valueOf(clazz, sValue);
Expand Down Expand Up @@ -424,4 +463,38 @@ else if (Character.TYPE.equals(clazz) || Character.class.equals(clazz)) {
return value;
}

private <T> T parseTemporalFromString(Object value, Method method, DateTimeFormatter defaultFormatter, TemporalQuery<T> query) throws JSONException {
try {
String sValue = (String) value;
JSON json = method.getAnnotation(JSON.class);

DateTimeFormatter formatter;
if (json != null && json.format().length() > 0) {
formatter = DateTimeFormatter.ofPattern(json.format());
} else {
formatter = defaultFormatter;
}
return formatter.parse(sValue, query);
} catch (Exception e) {
LOG.error("Unable to parse temporal from: {}", value, e);
throw new JSONException("Unable to parse temporal from: " + value);
}
}

private Instant parseInstantFromString(Object value, Method method) throws JSONException {
try {
String sValue = (String) value;
JSON json = method.getAnnotation(JSON.class);

if (json != null && json.format().length() > 0) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(json.format()).withZone(ZoneOffset.UTC);
return Instant.from(formatter.parse(sValue));
}
return Instant.parse(sValue);
} catch (Exception e) {
LOG.error("Unable to parse instant from: {}", value, e);
throw new JSONException("Unable to parse instant from: " + value);
}
}

}
Loading
Loading