diff --git a/src/main/java/com/avaje/ebean/config/JsonConfig.java b/src/main/java/com/avaje/ebean/config/JsonConfig.java index a813be3fe..06129c4db 100644 --- a/src/main/java/com/avaje/ebean/config/JsonConfig.java +++ b/src/main/java/com/avaje/ebean/config/JsonConfig.java @@ -26,4 +26,22 @@ public abstract class JsonConfig { ISO8601 } + + public enum Include { + + /** + * Include all values including null and empty collections. + */ + ALL, + + /** + * Exclude null values (include empty collections). + */ + NON_NULL, + + /** + * Exclude null values and empty collections. + */ + NON_EMPTY + } } diff --git a/src/main/java/com/avaje/ebean/config/ServerConfig.java b/src/main/java/com/avaje/ebean/config/ServerConfig.java index 503a904cf..7dfb23ace 100644 --- a/src/main/java/com/avaje/ebean/config/ServerConfig.java +++ b/src/main/java/com/avaje/ebean/config/ServerConfig.java @@ -123,6 +123,12 @@ public class ServerConfig { */ private JsonConfig.DateTime jsonDateTime = JsonConfig.DateTime.MILLIS; + /** + * For writing JSON specify if null values or empty collections should be exluded. + * By default all values are included. + */ + private JsonConfig.Include jsonInclude = JsonConfig.Include.ALL; + /** * The database platform name. Used to imply a DatabasePlatform to use. */ @@ -304,7 +310,7 @@ public class ServerConfig { /** * Return the Jackson JsonFactory to use. *

- * If not set a default implmentation will be used. + * If not set a default implementation will be used. */ public JsonFactory getJsonFactory() { return jsonFactory; @@ -313,7 +319,7 @@ public class ServerConfig { /** * Set the Jackson JsonFactory to use. *

- * If not set a default implmentation will be used. + * If not set a default implementation will be used. */ public void setJsonFactory(JsonFactory jsonFactory) { this.jsonFactory = jsonFactory; @@ -333,6 +339,23 @@ public class ServerConfig { this.jsonDateTime = jsonDateTime; } + /** + * Return the JSON include mode used when writing JSON. + */ + public JsonConfig.Include getJsonInclude() { + return jsonInclude; + } + + /** + * Set the JSON include mode used when writing JSON. + *

+ * Set to NON_NULL or NON_EMPTY to suppress nulls or null & empty collections respectively. + *

+ */ + public void setJsonInclude(JsonConfig.Include jsonInclude) { + this.jsonInclude = jsonInclude; + } + /** * Return the name of the EbeanServer. */ @@ -1784,7 +1807,7 @@ public class ServerConfig { int batchSize = p.getInt("batch.size", persistBatchSize); persistBatchSize = p.getInt("persistBatchSize", batchSize); - persistenceContextScope = PersistenceContextScope.valueOf(p.get("persistenceContextScope","TRANSACTION")); + persistenceContextScope = PersistenceContextScope.valueOf(p.get("persistenceContextScope", "TRANSACTION")); dataSourceJndiName = p.get("dataSourceJndiName", dataSourceJndiName); databaseSequenceBatchSize = p.getInt("databaseSequenceBatchSize", databaseSequenceBatchSize); @@ -1797,6 +1820,7 @@ public class ServerConfig { lazyLoadBatchSize = p.getInt("lazyLoadBatchSize", lazyLoadBatchSize); queryBatchSize = p.getInt("queryBatchSize", queryBatchSize); + jsonInclude = p.getEnum(JsonConfig.Include.class, "jsonInclude", jsonInclude); String jsonDateTimeFormat = p.get("jsonDateTime", null); if (jsonDateTimeFormat != null) { jsonDateTime = JsonConfig.DateTime.valueOf(jsonDateTimeFormat); diff --git a/src/main/java/com/avaje/ebean/text/json/JsonContext.java b/src/main/java/com/avaje/ebean/text/json/JsonContext.java index 4ef3da2e7..f5f52538c 100644 --- a/src/main/java/com/avaje/ebean/text/json/JsonContext.java +++ b/src/main/java/com/avaje/ebean/text/json/JsonContext.java @@ -163,8 +163,6 @@ public interface JsonContext { /** * Deprecated in favour of using PathProperties by itself. * Write json to the JsonGenerator using the JsonWriteOptions. - * - * @deprecated */ void toJson(Object value, JsonGenerator generator, JsonWriteOptions options) throws JsonIOException; @@ -173,7 +171,6 @@ public interface JsonContext { * With additional options. * * @throws JsonIOException When IOException occurs - * @deprecated */ void toJson(Object value, Writer writer, JsonWriteOptions options) throws JsonIOException; @@ -182,7 +179,6 @@ public interface JsonContext { * Convert a bean or collection to json string. * * @throws JsonIOException When IOException occurs - * @deprecated */ String toJson(Object value, JsonWriteOptions options) throws JsonIOException; diff --git a/src/main/java/com/avaje/ebean/text/json/JsonWriteOptions.java b/src/main/java/com/avaje/ebean/text/json/JsonWriteOptions.java index 5956ade30..8c2999a85 100644 --- a/src/main/java/com/avaje/ebean/text/json/JsonWriteOptions.java +++ b/src/main/java/com/avaje/ebean/text/json/JsonWriteOptions.java @@ -1,5 +1,6 @@ package com.avaje.ebean.text.json; +import com.avaje.ebean.config.JsonConfig; import com.avaje.ebean.text.PathProperties; /** @@ -15,6 +16,8 @@ public class JsonWriteOptions { protected Object objectMapper; + protected JsonConfig.Include include; + /** * Parse and return a PathProperties from nested string format like * (a,b,c(d,e),f(g)) where "c" is a path containing "d" and "e" and "f" is a @@ -50,6 +53,20 @@ public class JsonWriteOptions { return pathProperties; } + /** + * Return the include mode for this request. + */ + public JsonConfig.Include getInclude() { + return include; + } + + /** + * Set the include mode for this request. + */ + public void setInclude(JsonConfig.Include include) { + this.include = include; + } + /** * Return the jackson object mapper to use. *

diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanListHelp.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanListHelp.java index c3aa410cf..508cbd2c8 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanListHelp.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanListHelp.java @@ -2,7 +2,6 @@ package com.avaje.ebeaninternal.server.deploy; import java.io.IOException; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import com.avaje.ebean.EbeanServer; @@ -141,11 +140,13 @@ public final class BeanListHelp implements BeanCollectionHelp { list = (List) collection; } - ctx.writeStartArray(name); - for (int j = 0; j < list.size(); j++) { - targetDescriptor.jsonWrite(ctx, (EntityBean) list.get(j)); + if (!list.isEmpty() || ctx.isIncludeEmpty()) { + ctx.writeStartArray(name); + for (int j = 0; j < list.size(); j++) { + targetDescriptor.jsonWrite(ctx, (EntityBean) list.get(j)); + } + ctx.writeEndArray(); } - ctx.writeEndArray(); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanMapHelp.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanMapHelp.java index e7cace23e..d74aa48fc 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanMapHelp.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanMapHelp.java @@ -177,12 +177,14 @@ public final class BeanMapHelp implements BeanCollectionHelp { map = (Map) collection; } - ctx.writeStartArray(name); - for (Entry entry : map.entrySet()) { - //FIXME: json write map key ... - targetDescriptor.jsonWrite(ctx, (EntityBean) entry.getValue()); + if (!map.isEmpty() || ctx.isIncludeEmpty()) { + ctx.writeStartArray(name); + for (Entry entry : map.entrySet()) { + //FIXME: json write map key ... + targetDescriptor.jsonWrite(ctx, (EntityBean) entry.getValue()); + } + ctx.writeEndArray(); } - ctx.writeEndArray(); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanProperty.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanProperty.java index 69fe731f5..d3acb11a4 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanProperty.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanProperty.java @@ -1074,10 +1074,10 @@ public class BeanProperty implements ElPropertyValue { } Object value = getValueIntercept(bean); if (value == null) { - writeJson.writeNull(name); + writeJson.writeNullField(name); } else { if (scalarType != null) { - scalarType.jsonWrite(writeJson.gen(), name, value); + scalarType.jsonWrite(writeJson, name, value); } else { writeJson.writeValueUsingObjectMapper(name, value); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocMany.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocMany.java index 5c234c63b..d4f3c3488 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocMany.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocMany.java @@ -876,7 +876,10 @@ public class BeanPropertyAssocMany extends BeanPropertyAssoc { if (isTransient) { ctx.writeValueUsingObjectMapper(name, value); } else { - ctx.toJson(name, (Collection) value); + Collection collection = (Collection)value; + if (!collection.isEmpty() || ctx.isIncludeEmpty()) { + ctx.toJson(name, collection); + } } } ctx.popParentBeanMany(); diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocOne.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocOne.java index 5c1b5aaa1..a98c71da3 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocOne.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocOne.java @@ -830,7 +830,7 @@ public class BeanPropertyAssocOne extends BeanPropertyAssoc { Object value = getValueIntercept(bean); if (value == null) { - writeJson.writeNull(name); + writeJson.writeNullField(name); } else { if (writeJson.isParentBean(value)) { diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyCompound.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyCompound.java index ac241d8d6..babe6c835 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyCompound.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyCompound.java @@ -171,7 +171,7 @@ public class BeanPropertyCompound extends BeanProperty { } Object value = getValueIntercept(bean); if (value == null) { - ctx.writeNull(name); + ctx.writeNullField(name); } else { compoundType.jsonWrite(ctx, value, name); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanSetHelp.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanSetHelp.java index f7cd0e67b..be4eb7d4d 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanSetHelp.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanSetHelp.java @@ -139,11 +139,13 @@ public final class BeanSetHelp implements BeanCollectionHelp { set = (Set) collection; } - ctx.writeStartArray(name); - Iterator it = set.iterator(); - while (it.hasNext()) { - targetDescriptor.jsonWrite(ctx, (EntityBean) it.next()); + if (!set.isEmpty() || ctx.isIncludeEmpty()) { + ctx.writeStartArray(name); + Iterator it = set.iterator(); + while (it.hasNext()) { + targetDescriptor.jsonWrite(ctx, (EntityBean) it.next()); + } + ctx.writeEndArray(); } - ctx.writeEndArray(); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/text/json/DJsonContext.java b/src/main/java/com/avaje/ebeaninternal/server/text/json/DJsonContext.java index 175907584..00e49d017 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/text/json/DJsonContext.java +++ b/src/main/java/com/avaje/ebeaninternal/server/text/json/DJsonContext.java @@ -1,6 +1,7 @@ package com.avaje.ebeaninternal.server.text.json; import com.avaje.ebean.bean.EntityBean; +import com.avaje.ebean.config.JsonConfig; import com.avaje.ebean.text.json.*; import com.avaje.ebean.text.PathProperties; import com.avaje.ebeaninternal.api.SpiEbeanServer; @@ -26,10 +27,13 @@ public class DJsonContext implements JsonContext { private final Object defaultObjectMapper; + private final JsonConfig.Include defaultInclude; + public DJsonContext(SpiEbeanServer server, JsonFactory jsonFactory) { this.server = server; this.jsonFactory = (jsonFactory != null) ? jsonFactory : new JsonFactory(); this.defaultObjectMapper = this.server.getServerConfig().getObjectMapper(); + this.defaultInclude = this.server.getServerConfig().getJsonInclude(); } public boolean isSupportedType(Type genericType) { @@ -274,7 +278,7 @@ public class DJsonContext implements JsonContext { private WriteJson createWriteJson(JsonGenerator gen, JsonWriteOptions options) { PathProperties pathProps = (options == null) ? null : options.getPathProperties(); - return new WriteJson(server, gen, pathProps, determineObjectMapper(options)); + return new WriteJson(server, gen, pathProps, determineObjectMapper(options), determineInclude(options)); } private void toJsonFromCollection(Collection collection, String key, JsonGenerator gen, JsonWriteOptions options) throws IOException { @@ -355,4 +359,15 @@ public class DJsonContext implements JsonContext { Object mapper = options.getObjectMapper(); return (mapper != null) ? mapper : defaultObjectMapper; } + + /** + * Determine the include mode to use for a JSON write request. + */ + private JsonConfig.Include determineInclude(JsonWriteOptions options) { + if (options == null) { + return defaultInclude; + } + JsonConfig.Include include = options.getInclude(); + return (include != null) ? include : defaultInclude; + } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/text/json/WriteJson.java b/src/main/java/com/avaje/ebeaninternal/server/text/json/WriteJson.java index cb6452c3f..9a5500dca 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/text/json/WriteJson.java +++ b/src/main/java/com/avaje/ebeaninternal/server/text/json/WriteJson.java @@ -1,19 +1,24 @@ package com.avaje.ebeaninternal.server.text.json; import com.avaje.ebean.bean.EntityBean; +import com.avaje.ebean.config.JsonConfig; import com.avaje.ebean.text.PathProperties; import com.avaje.ebeaninternal.api.SpiEbeanServer; import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; import com.avaje.ebeaninternal.server.deploy.BeanProperty; +import com.avaje.ebeaninternal.server.type.JsonWriter; import com.avaje.ebeaninternal.server.util.ArrayStack; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; +import java.io.InputStream; +import java.math.BigDecimal; import java.util.Collection; +import java.util.Map; import java.util.Set; -public class WriteJson { +public class WriteJson implements JsonWriter { private final SpiEbeanServer server; @@ -27,17 +32,105 @@ public class WriteJson { private final Object objectMapper; - public WriteJson(SpiEbeanServer server, JsonGenerator generator, PathProperties pathProperties, Object objectMapper){ + private final JsonConfig.Include include; + + public WriteJson(SpiEbeanServer server, JsonGenerator generator, PathProperties pathProperties, Object objectMapper, JsonConfig.Include include){ this.server = server; this.generator = generator; this.pathProperties = pathProperties; this.objectMapper = objectMapper; + this.include = include; + } + + /** + * Construct for testing purposes only. + */ + public WriteJson(JsonGenerator generator, JsonConfig.Include include) { + this(null, generator, null, null, include); + } + + /** + * Return true if null values should be included in JSON output. + */ + public boolean isIncludeNull() { + return include == JsonConfig.Include.ALL; + } + + /** + * Return true if empty collections should be included in the JSON output. + */ + public boolean isIncludeEmpty() { + return include != JsonConfig.Include.NON_EMPTY; } public JsonGenerator gen() { return generator; } + @Override + public void writeFieldName(String name) throws IOException { + generator.writeFieldName(name); + } + + @Override + public void writeNullField(String name) throws IOException { + if (isIncludeNull()) { + generator.writeNullField(name); + } + } + + @Override + public void writeNumberField(String name, Long value) throws IOException { + generator.writeNumberField(name, value); + } + + @Override + public void writeNumberField(String name, Double value) throws IOException { + generator.writeNumberField(name, value); + } + + @Override + public void writeNumberField(String name, int value) throws IOException { + generator.writeNumberField(name, value); + } + + @Override + public void writeNumberField(String name, Short value) throws IOException { + generator.writeNumberField(name, value); + } + + + @Override + public void writeNumberField(String name, Float value) throws IOException { + generator.writeNumberField(name, value); + } + + + @Override + public void writeNumberField(String name, BigDecimal value) throws IOException { + generator.writeNumberField(name, value); + } + + @Override + public void writeStringField(String name, String value) throws IOException { + generator.writeStringField(name, value); + } + + @Override + public void writeBinary(InputStream is, int length) throws IOException { + generator.writeBinary(is, length); + } + + @Override + public void writeBinaryField(String name, byte[] value) throws IOException { + generator.writeBinaryField(name, value); + } + + @Override + public void writeBooleanField(String name, Boolean value) throws IOException { + generator.writeBooleanField(name, value); + } + public boolean isParentBean(Object bean) { return !parentBeans.isEmpty() && parentBeans.contains(bean); } @@ -78,6 +171,17 @@ public class WriteJson { } public void writeValueUsingObjectMapper(String name, Object value) throws IOException { + + if (!isIncludeEmpty()) { + // check for suppression of empty collection or map + if (value instanceof Collection && ((Collection)value).isEmpty()) { + // suppress empty collection + return; + } else if (value instanceof Map && ((Map)value).isEmpty()) { + // suppress empty map + return; + } + } generator.writeFieldName(name); objectMapper().writeValue(generator, value); } @@ -215,10 +319,6 @@ public class WriteJson { } generator.writeStartObject(); } - - public void writeNull(String name) throws IOException { - generator.writeNullField(name); - } public void writeEndObject() throws IOException { generator.writeEndObject(); diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/CtCompoundType.java b/src/main/java/com/avaje/ebeaninternal/server/type/CtCompoundType.java index 25c04ba21..58e38cb9e 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/CtCompoundType.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/CtCompoundType.java @@ -197,7 +197,7 @@ public final class CtCompoundType implements ScalarDataReader { ((CtCompoundType) propReaders[i]).jsonWrite(ctx, value, propName); } else { - ((ScalarType) propReaders[i]).jsonWrite(ctx.gen(), propName, value); + ((ScalarType) propReaders[i]).jsonWrite(ctx, propName, value); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/JsonWriter.java b/src/main/java/com/avaje/ebeaninternal/server/type/JsonWriter.java new file mode 100644 index 000000000..469b1141f --- /dev/null +++ b/src/main/java/com/avaje/ebeaninternal/server/type/JsonWriter.java @@ -0,0 +1,88 @@ +package com.avaje.ebeaninternal.server.type; + +import com.fasterxml.jackson.core.JsonGenerator; + +import java.io.IOException; +import java.io.InputStream; +import java.math.BigDecimal; + +/** + * Wraps an underlying JsonGenerator taking into account null suppression and exposing isIncludeEmpty() etc. + */ +public interface JsonWriter { + + /** + * Return the Jackson core JsonGenerator. + */ + JsonGenerator gen(); + + /** + * Return true if null values should be included in JSON output. + */ + boolean isIncludeNull(); + + /** + * Return true if empty collections should be included in the JSON output. + */ + boolean isIncludeEmpty(); + + /** + * Write the field name. + */ + void writeFieldName(String name) throws IOException; + + /** + * Write a null value taking into account null value suppression. + */ + void writeNullField(String name) throws IOException; + + /** + * Write a number field. + */ + void writeNumberField(String name, int value) throws IOException; + + /** + * Write a number field. + */ + void writeNumberField(String name, Short value) throws IOException; + + /** + * Write a number field. + */ + void writeNumberField(String name, Long value) throws IOException; + + /** + * Write a number field. + */ + void writeNumberField(String name, Double value) throws IOException; + + /** + * Write a number field. + */ + void writeNumberField(String name, Float value) throws IOException; + + /** + * Write a number field. + */ + void writeNumberField(String name, BigDecimal value) throws IOException; + + /** + * Write a sting field. + */ + void writeStringField(String name, String value) throws IOException; + + /** + * Write a binary field. + */ + void writeBinary(InputStream is, int length) throws IOException; + + /** + * Write a binary field. + */ + void writeBinaryField(String name, byte[] value) throws IOException; + + /** + * Write a boolean field. + */ + void writeBooleanField(String name, Boolean value) throws IOException; +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarType.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarType.java index 03a2323e9..619e87b3c 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarType.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarType.java @@ -202,6 +202,6 @@ public interface ScalarType extends StringParser, StringFormatter, ScalarData /** * Write the value to the JsonGenerator. */ - void jsonWrite(JsonGenerator ctx, String name, T value) throws IOException; + void jsonWrite(JsonWriter writer, String name, T value) throws IOException; } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBaseDate.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBaseDate.java index 105441148..051520772 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBaseDate.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBaseDate.java @@ -77,9 +77,9 @@ public abstract class ScalarTypeBaseDate extends ScalarTypeBase { } } - public void jsonWrite(JsonGenerator ctx, String name, T value) throws IOException { + public void jsonWrite(JsonWriter writer, String name, T value) throws IOException { long millis = convertToMillis(value); - ctx.writeNumberField(name, millis); + writer.writeNumberField(name, millis); } public T readData(DataInput dataInput) throws IOException { diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBaseDateTime.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBaseDateTime.java index 984a48f13..e5568eb43 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBaseDateTime.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBaseDateTime.java @@ -103,21 +103,21 @@ public abstract class ScalarTypeBaseDateTime extends ScalarTypeBase { } @Override - public void jsonWrite(JsonGenerator generator, String name, T value) throws IOException { + public void jsonWrite(JsonWriter writer, String name, T value) throws IOException { switch (mode) { case ISO8601: { - generator.writeFieldName(name); - generator.writeString(toJsonISO8601(value)); + writer.writeFieldName(name); + writer.gen().writeString(toJsonISO8601(value)); break; } case NANOS: { - generator.writeFieldName(name); - generator.writeNumber(toJsonNanos(value)); + writer.writeFieldName(name); + writer.gen().writeNumber(toJsonNanos(value)); break; } default: { - generator.writeNumberField(name, convertToMillis(value)); + writer.gen().writeNumberField(name, convertToMillis(value)); } } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBaseVarchar.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBaseVarchar.java index 79c19c197..db5a4b9dd 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBaseVarchar.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBaseVarchar.java @@ -128,7 +128,7 @@ public abstract class ScalarTypeBaseVarchar extends ScalarTypeBase { } @Override - public void jsonWrite(JsonGenerator ctx, String name, T value) throws IOException { - ctx.writeStringField(name, format(value)); + public void jsonWrite(JsonWriter writer, String name, T value) throws IOException { + writer.writeStringField(name, format(value)); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBigDecimal.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBigDecimal.java index a5abb5d99..757fc5f3e 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBigDecimal.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBigDecimal.java @@ -82,8 +82,9 @@ public class ScalarTypeBigDecimal extends ScalarTypeBase { return ctx.getDecimalValue(); } - public void jsonWrite(JsonGenerator ctx, String name, BigDecimal value) throws IOException { - ctx.writeNumberField(name, value); + @Override + public void jsonWrite(JsonWriter writer, String name, BigDecimal value) throws IOException { + writer.writeNumberField(name, value); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBoolean.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBoolean.java index 9a38561ae..05cd4ebf1 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBoolean.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBoolean.java @@ -284,8 +284,9 @@ public class ScalarTypeBoolean { return JsonToken.VALUE_TRUE == event ? Boolean.TRUE : Boolean.FALSE; } - public void jsonWrite(JsonGenerator ctx, String name, Boolean value) throws IOException { - ctx.writeBooleanField(name, value); + @Override + public void jsonWrite(JsonWriter writer, String name, Boolean value) throws IOException { + writer.writeBooleanField(name, value); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeByte.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeByte.java index bc6872eaf..a5b3e8cb8 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeByte.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeByte.java @@ -42,7 +42,7 @@ public class ScalarTypeByte extends ScalarTypeBase { } @Override - public void jsonWrite(JsonGenerator ctx, String name, Byte value) throws IOException { + public void jsonWrite(JsonWriter writer, String name, Byte value) throws IOException { throw new IOException("Not supported"); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBytesBase.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBytesBase.java index 405672490..42f6bd1ff 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBytesBase.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBytesBase.java @@ -41,8 +41,8 @@ public abstract class ScalarTypeBytesBase extends ScalarTypeBase { } @Override - public void jsonWrite(JsonGenerator ctx, String name, byte[] value) throws IOException { - ctx.writeBinaryField(name, value); + public void jsonWrite(JsonWriter writer, String name, byte[] value) throws IOException { + writer.writeBinaryField(name, value); } @Override diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBytesEncrypted.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBytesEncrypted.java index 439ccf4ad..09a83db3a 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBytesEncrypted.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBytesEncrypted.java @@ -64,8 +64,8 @@ public class ScalarTypeBytesEncrypted implements ScalarType { } @Override - public void jsonWrite(JsonGenerator ctx, String name, byte[] value) throws IOException { - ctx.writeBinaryField(name, value); + public void jsonWrite(JsonWriter writer, String name, byte[] value) throws IOException { + writer.writeBinaryField(name, value); } @Override diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeDouble.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeDouble.java index 979529583..ee9161f17 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeDouble.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeDouble.java @@ -90,7 +90,7 @@ public class ScalarTypeDouble extends ScalarTypeBase { } @Override - public void jsonWrite(JsonGenerator ctx, String name, Double value) throws IOException { - ctx.writeNumberField(name, value); + public void jsonWrite(JsonWriter writer, String name, Double value) throws IOException { + writer.writeNumberField(name, value); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeDuration.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeDuration.java index f224b8f6d..475096cd5 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeDuration.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeDuration.java @@ -107,7 +107,7 @@ public class ScalarTypeDuration extends ScalarTypeBase { } @Override - public void jsonWrite(JsonGenerator ctx, String name, Duration value) throws IOException { - ctx.writeStringField(name, value.toString()); + public void jsonWrite(JsonWriter writer, String name, Duration value) throws IOException { + writer.writeStringField(name, value.toString()); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeEncryptedWrapper.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeEncryptedWrapper.java index ca5901a01..40f49baf1 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeEncryptedWrapper.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeEncryptedWrapper.java @@ -138,7 +138,7 @@ public class ScalarTypeEncryptedWrapper implements ScalarType { } @Override - public void jsonWrite(JsonGenerator ctx, String name, T value) throws IOException { - wrapped.jsonWrite(ctx, name, value); + public void jsonWrite(JsonWriter writer, String name, T value) throws IOException { + wrapped.jsonWrite(writer, name, value); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeEnumStandard.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeEnumStandard.java index cfc018667..d34f114a1 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeEnumStandard.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeEnumStandard.java @@ -237,8 +237,8 @@ public class ScalarTypeEnumStandard { } @Override - public void jsonWrite(JsonGenerator ctx, String name, Object value) throws IOException { - ctx.writeStringField(name, formatValue(value)); + public void jsonWrite(JsonWriter writer, String name, Object value) throws IOException { + writer.writeStringField(name, formatValue(value)); } @Override diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeFile.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeFile.java index ca6a6a6fe..bd0db71b2 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeFile.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeFile.java @@ -102,10 +102,10 @@ public class ScalarTypeFile extends ScalarTypeBase { } @Override - public void jsonWrite(JsonGenerator ctx, String name, File value) throws IOException { - ctx.writeFieldName(name); + public void jsonWrite(JsonWriter writer, String name, File value) throws IOException { + writer.writeFieldName(name); InputStream is = getInputStream(value); - ctx.writeBinary(is, (int) value.length()); + writer.writeBinary(is, (int) value.length()); } @Override diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeFloat.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeFloat.java index b9276dce6..1095ac35e 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeFloat.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeFloat.java @@ -90,7 +90,7 @@ public class ScalarTypeFloat extends ScalarTypeBase { } @Override - public void jsonWrite(JsonGenerator ctx, String name, Float value) throws IOException { - ctx.writeNumberField(name, value); + public void jsonWrite(JsonWriter writer, String name, Float value) throws IOException { + writer.writeNumberField(name, value); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeInteger.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeInteger.java index 574b16895..4f31b1cd9 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeInteger.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeInteger.java @@ -90,7 +90,7 @@ public class ScalarTypeInteger extends ScalarTypeBase { } @Override - public void jsonWrite(JsonGenerator ctx, String name, Integer value) throws IOException { - ctx.writeNumberField(name, value); + public void jsonWrite(JsonWriter writer, String name, Integer value) throws IOException { + writer.writeNumberField(name, value); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeJodaLocalTime.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeJodaLocalTime.java index c3cd766c6..a7be53060 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeJodaLocalTime.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeJodaLocalTime.java @@ -72,8 +72,8 @@ public class ScalarTypeJodaLocalTime extends ScalarTypeBase { } @Override - public void jsonWrite(JsonGenerator ctx, String name, LocalTime value) throws IOException { - ctx.writeStringField(name, value.toString()); + public void jsonWrite(JsonWriter writer, String name, LocalTime value) throws IOException { + writer.writeStringField(name, value.toString()); } @Override diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeJsonMap.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeJsonMap.java index 3f80ce5c2..581d9ffb6 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeJsonMap.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeJsonMap.java @@ -193,13 +193,15 @@ public abstract class ScalarTypeJsonMap extends ScalarTypeBase { } @Override - public void jsonWrite(JsonGenerator ctx, String name, Map value) throws IOException { + public void jsonWrite(JsonWriter writer, String name, Map value) throws IOException { // write the field name followed by the Map/JSON Object if (value == null) { - ctx.writeNullField(name); + writer.writeNullField(name); } else { - ctx.writeFieldName(name); - EJson.write(value, ctx); + if (!value.isEmpty() || writer.isIncludeEmpty()) { + writer.writeFieldName(name); + EJson.write(value, writer.gen()); + } } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeJsonNode.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeJsonNode.java index 9dc44579e..be6df4b96 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeJsonNode.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeJsonNode.java @@ -207,13 +207,13 @@ public abstract class ScalarTypeJsonNode extends ScalarTypeBase { } @Override - public void jsonWrite(JsonGenerator ctx, String name, JsonNode value) throws IOException { + public void jsonWrite(JsonWriter writer, String name, JsonNode value) throws IOException { // write the field name followed by the JsonNode object if (value == null) { - ctx.writeNullField(name); + writer.writeNullField(name); } else { - ctx.writeFieldName(name); - objectMapper.writeTree(ctx, value); + writer.writeFieldName(name); + objectMapper.writeTree(writer.gen(), value); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeLocalTime.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeLocalTime.java index 2dcfeb079..3bd46b121 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeLocalTime.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeLocalTime.java @@ -99,7 +99,7 @@ public class ScalarTypeLocalTime extends ScalarTypeBase { } @Override - public void jsonWrite(JsonGenerator ctx, String name, LocalTime value) throws IOException { - ctx.writeStringField(name, value.toString()); + public void jsonWrite(JsonWriter writer, String name, LocalTime value) throws IOException { + writer.writeStringField(name, value.toString()); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeLong.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeLong.java index 2a114c08a..660622648 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeLong.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeLong.java @@ -90,7 +90,7 @@ public class ScalarTypeLong extends ScalarTypeBase { } @Override - public void jsonWrite(JsonGenerator ctx, String name, Long value) throws IOException { - ctx.writeNumberField(name, value); + public void jsonWrite(JsonWriter writer, String name, Long value) throws IOException { + writer.writeNumberField(name, value); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeMathBigInteger.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeMathBigInteger.java index 60d56cd23..05f62ab57 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeMathBigInteger.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeMathBigInteger.java @@ -97,8 +97,8 @@ public class ScalarTypeMathBigInteger extends ScalarTypeBase { } @Override - public void jsonWrite(JsonGenerator ctx, String name, BigInteger value) throws IOException { - ctx.writeNumberField(name, value.longValue()); + public void jsonWrite(JsonWriter writer, String name, BigInteger value) throws IOException { + writer.writeNumberField(name, value.longValue()); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeMonthDay.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeMonthDay.java index 417f80bc2..e948352ca 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeMonthDay.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeMonthDay.java @@ -124,8 +124,8 @@ public class ScalarTypeMonthDay extends ScalarTypeBase { } @Override - public void jsonWrite(JsonGenerator ctx, String name, MonthDay value) throws IOException { - ctx.writeStringField(name, format(value)); + public void jsonWrite(JsonWriter writer, String name, MonthDay value) throws IOException { + writer.writeStringField(name, format(value)); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypePostgresHstore.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypePostgresHstore.java index 2c04d0175..8723dce8f 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypePostgresHstore.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypePostgresHstore.java @@ -112,13 +112,13 @@ public class ScalarTypePostgresHstore extends ScalarTypeBase { } @Override - public void jsonWrite(JsonGenerator ctx, String name, Map value) throws IOException { + public void jsonWrite(JsonWriter writer, String name, Map value) throws IOException { // write the field name followed by the Map/JSON Object if (value == null) { - ctx.writeNullField(name); + writer.writeNullField(name); } else { - ctx.writeFieldName(name); - EJson.write(value, ctx); + writer.writeFieldName(name); + EJson.write(value, writer.gen()); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeShort.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeShort.java index f1993c50a..f5034b89e 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeShort.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeShort.java @@ -91,7 +91,7 @@ public class ScalarTypeShort extends ScalarTypeBase { } @Override - public void jsonWrite(JsonGenerator ctx, String name, Short value) throws IOException { - ctx.writeNumberField(name, value); + public void jsonWrite(JsonWriter writer, String name, Short value) throws IOException { + writer.writeNumberField(name, value); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeString.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeString.java index a9fd9c72a..437992657 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeString.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeString.java @@ -90,7 +90,7 @@ public class ScalarTypeString extends ScalarTypeBase { } @Override - public void jsonWrite(JsonGenerator ctx, String name, String value) throws IOException { - ctx.writeStringField(name, value); + public void jsonWrite(JsonWriter writer, String name, String value) throws IOException { + writer.writeStringField(name, value); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeTime.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeTime.java index eb0b51d2f..737c4393a 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeTime.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeTime.java @@ -92,8 +92,8 @@ public class ScalarTypeTime extends ScalarTypeBase