diff --git a/docs/LIBRARY.md b/docs/LIBRARY.md
index 82e27c985..9e8b86fb5 100644
--- a/docs/LIBRARY.md
+++ b/docs/LIBRARY.md
@@ -183,6 +183,7 @@ database.save(customer);
| Configure database and `Database` bean | [add-ebean-postgres-database-config.md](guides/add-ebean-postgres-database-config.md) |
| Add PostgreSQL test container support | [add-ebean-postgres-test-container.md](guides/add-ebean-postgres-test-container.md) |
| Generate DB migrations | [add-ebean-db-migration-generation.md](guides/add-ebean-db-migration-generation.md) |
+| Migrate JSON APIs from Jackson core to avaje-json-core | [migrating-json-jackson-core-to-avaje-json-core.md](guides/migrating-json-jackson-core-to-avaje-json-core.md) |
| Model entity beans correctly | [entity-bean-creation.md](guides/entity-bean-creation.md) |
| Use Lombok safely with entities | [lombok-with-ebean-entity-beans.md](guides/lombok-with-ebean-entity-beans.md) |
| Write type-safe query bean queries | [writing-ebean-query-beans.md](guides/writing-ebean-query-beans.md) |
diff --git a/docs/guides/AGENTS.md b/docs/guides/AGENTS.md
index 0fec50b33..4109ab263 100644
--- a/docs/guides/AGENTS.md
+++ b/docs/guides/AGENTS.md
@@ -12,6 +12,7 @@ Key guides (fetch and follow when performing the relevant task):
- Maven POM setup: https://raw.githubusercontent.com/ebean-orm/ebean/HEAD/docs/guides/add-ebean-postgres-maven-pom.md
- Database configuration: https://raw.githubusercontent.com/ebean-orm/ebean/HEAD/docs/guides/add-ebean-postgres-database-config.md
- Migrate to `Database.builder()`: https://raw.githubusercontent.com/ebean-orm/ebean/HEAD/docs/guides/migrating-to-database-builder.md
+- Migrate JSON APIs from Jackson core to avaje-json-core: https://raw.githubusercontent.com/ebean-orm/ebean/HEAD/docs/guides/migrating-json-jackson-core-to-avaje-json-core.md
- Write queries with query beans: https://raw.githubusercontent.com/ebean-orm/ebean/HEAD/docs/guides/writing-ebean-query-beans.md
- Persisting and transactions: https://raw.githubusercontent.com/ebean-orm/ebean/HEAD/docs/guides/persisting-and-transactions-with-ebean.md
- Query metrics and naming: https://raw.githubusercontent.com/ebean-orm/ebean/HEAD/docs/guides/ebean-query-metrics.md
diff --git a/docs/guides/README.md b/docs/guides/README.md
index b85a87b7b..a9432d6c5 100644
--- a/docs/guides/README.md
+++ b/docs/guides/README.md
@@ -23,6 +23,7 @@ existing Maven project. Complete the steps in order.
| Guide | Description |
|-------|-------------|
| [Migrate to `Database.builder()`](migrating-to-database-builder.md) | Replace legacy `new DatabaseConfig()` and `DatabaseFactory.create(...)` code with `Database.builder()` and `DatabaseBuilder.build()`. Includes common rewrites, fluent builder equivalents, and manual-review cases for semi-automated upgrades |
+| [Migrate JSON APIs from Jackson core to avaje-json-core](migrating-json-jackson-core-to-avaje-json-core.md) | Cut over `JsonParser`/`JsonGenerator`/`JsonFactory` usage to `JsonReader`/`JsonWriter`/`JsonStream`, including `DatabaseBuilder`/`DatabaseConfig` JSON config changes and validation checklist |
## Observability
diff --git a/docs/guides/migrating-json-jackson-core-to-avaje-json-core.md b/docs/guides/migrating-json-jackson-core-to-avaje-json-core.md
new file mode 100644
index 000000000..da7fbc218
--- /dev/null
+++ b/docs/guides/migrating-json-jackson-core-to-avaje-json-core.md
@@ -0,0 +1,91 @@
+# Guide: Migrate JSON APIs from Jackson core to avaje-json-core
+
+## Purpose
+
+This guide covers the one-step cutover in Ebean from Jackson core JSON APIs to
+avaje-json-core APIs.
+
+Use this when upgrading code that references:
+
+- `com.fasterxml.jackson.core.JsonParser`
+- `com.fasterxml.jackson.core.JsonGenerator`
+- `com.fasterxml.jackson.core.JsonFactory`
+
+The replacement types are:
+
+- `io.avaje.json.JsonReader`
+- `io.avaje.json.JsonWriter`
+- `io.avaje.json.stream.JsonStream`
+
+---
+
+## Breaking API changes
+
+| Previous API | New API |
+|---|---|
+| `JsonParser` | `JsonReader` |
+| `JsonGenerator` | `JsonWriter` |
+| `JsonFactory` | `JsonStream` |
+| `DatabaseBuilder.jsonFactory(...)` | `DatabaseBuilder.jsonStream(...)` |
+| `DatabaseConfig.getJsonFactory()/setJsonFactory(...)` | `DatabaseConfig.getJsonStream()/setJsonStream(...)` |
+
+---
+
+## Typical migration rewrites
+
+### Parser and generator signatures
+
+```java
+// before
+void read(JsonParser parser)
+void write(JsonGenerator generator)
+
+// after
+void read(JsonReader parser)
+void write(JsonWriter generator)
+```
+
+### Database configuration
+
+```java
+// before
+Database.builder().jsonFactory(factory)
+
+// after
+Database.builder().jsonStream(stream)
+```
+
+### JSON utility calls
+
+`EJson` and `JsonContext` APIs now operate on `JsonReader` and `JsonWriter` types.
+If your code was calling those APIs with Jackson core types, switch to avaje types.
+
+---
+
+## Dependency and module notes
+
+- `ebean-core` no longer requires a direct `jackson-core` dependency for JSON
+ parsing/writing.
+- `jackson-databind` remains optional for `ObjectMapper` compatibility paths.
+- `ebean-jackson-mapper` remains the compatibility bridge module for mapper-based
+ integrations.
+
+---
+
+## Behavior notes to verify during upgrade
+
+1. Parser token handling is now based on avaje `JsonReader.Token`.
+2. Scalar JSON reads (for example booleans, date-time, array scalar types) should
+ be validated in your tests if you previously depended on Jackson token quirks.
+3. If your integration uses transient assoc-many JSON mapping with ObjectMapper,
+ keep ObjectMapper wiring enabled.
+
+---
+
+## Validation checklist
+
+1. Compile all modules that implement or consume `io.ebean.text.json` APIs.
+2. Run module tests that cover JSON scalar conversion and bean JSON round-trips.
+3. Confirm no remaining `com.fasterxml.jackson.core.*` imports in migrated code.
+4. Keep `ObjectMapper` compatibility tests if your project depends on mapper paths.
+
diff --git a/ebean-api/pom.xml b/ebean-api/pom.xml
index e7435fbdc..5d7b43c81 100644
--- a/ebean-api/pom.xml
+++ b/ebean-api/pom.xml
@@ -70,15 +70,13 @@
true
-
- com.fasterxml.jackson.core
- jackson-core
- ${jackson.version}
- true
+ io.avaje
+ avaje-json-core
+ ${avaje-json-core.version}
-
+
com.fasterxml.jackson.corejackson-databind
diff --git a/ebean-api/src/main/java/io/ebean/DatabaseBuilder.java b/ebean-api/src/main/java/io/ebean/DatabaseBuilder.java
index 0f1c6eeeb..51e6f9618 100644
--- a/ebean-api/src/main/java/io/ebean/DatabaseBuilder.java
+++ b/ebean-api/src/main/java/io/ebean/DatabaseBuilder.java
@@ -1,6 +1,6 @@
package io.ebean;
-import com.fasterxml.jackson.core.JsonFactory;
+import io.avaje.json.stream.JsonStream;
import io.ebean.annotation.*;
import io.ebean.cache.ServerCachePlugin;
import io.ebean.config.*;
@@ -360,18 +360,18 @@ public interface DatabaseBuilder {
DatabaseBuilder putServiceObject(Object configObject);
/**
- * Set the Jackson JsonFactory to use.
+ * Set the JsonStream to use.
*
* If not set a default implementation will be used.
*/
- default DatabaseBuilder jsonFactory(JsonFactory jsonFactory) {
- return setJsonFactory(jsonFactory);
+ default DatabaseBuilder jsonStream(JsonStream jsonStream) {
+ return setJsonStream(jsonStream);
}
/**
- * @deprecated migrate to {@link #jsonFactory(JsonFactory)}.
+ * @deprecated migrate to {@link #jsonStream(JsonStream)}.
*/
- DatabaseBuilder setJsonFactory(JsonFactory jsonFactory);
+ DatabaseBuilder setJsonStream(JsonStream jsonStream);
/**
* Set the JSON format to use for DateTime types.
@@ -2254,11 +2254,11 @@ public interface DatabaseBuilder {
boolean isAutoLoadModuleInfo();
/**
- * Return the Jackson JsonFactory to use.
+ * Return the JsonStream to use.
*
* If not set a default implementation will be used.
*/
- JsonFactory getJsonFactory();
+ JsonStream getJsonStream();
/**
* Get the clock used for setting the timestamps (e.g. @UpdatedTimestamp) on objects.
diff --git a/ebean-api/src/main/java/io/ebean/config/ClassLoadConfig.java b/ebean-api/src/main/java/io/ebean/config/ClassLoadConfig.java
index 7fa749ca8..8a1bf02ab 100644
--- a/ebean-api/src/main/java/io/ebean/config/ClassLoadConfig.java
+++ b/ebean-api/src/main/java/io/ebean/config/ClassLoadConfig.java
@@ -60,7 +60,8 @@ public class ClassLoadConfig {
}
public boolean isJacksonCorePresent() {
- return isPresent("com.fasterxml.jackson.core.JsonParser");
+ // Legacy method name retained for compatibility; now checks avaje JSON core.
+ return isPresent("io.avaje.json.JsonReader");
}
/**
@@ -158,4 +159,3 @@ public class ClassLoadConfig {
}
}
}
-
diff --git a/ebean-api/src/main/java/io/ebean/config/DatabaseConfig.java b/ebean-api/src/main/java/io/ebean/config/DatabaseConfig.java
index 3c3624573..33dbf399f 100644
--- a/ebean-api/src/main/java/io/ebean/config/DatabaseConfig.java
+++ b/ebean-api/src/main/java/io/ebean/config/DatabaseConfig.java
@@ -1,7 +1,7 @@
package io.ebean.config;
-import com.fasterxml.jackson.core.JsonFactory;
import io.avaje.config.Config;
+import io.avaje.json.stream.JsonStream;
import io.ebean.*;
import io.ebean.annotation.MutationDetection;
import io.ebean.annotation.PersistBatch;
@@ -420,7 +420,7 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
* The default PersistenceContextScope used if one is not explicitly set on a query.
*/
private PersistenceContextScope persistenceContextScope = PersistenceContextScope.TRANSACTION;
- private JsonFactory jsonFactory;
+ private JsonStream jsonStream;
private boolean localTimeWithNanos;
private boolean durationWithNanos;
private int maxCallStack = 5;
@@ -631,13 +631,13 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
}
@Override
- public JsonFactory getJsonFactory() {
- return jsonFactory;
+ public JsonStream getJsonStream() {
+ return jsonStream;
}
@Override
- public DatabaseConfig setJsonFactory(JsonFactory jsonFactory) {
- this.jsonFactory = jsonFactory;
+ public DatabaseConfig setJsonStream(JsonStream jsonStream) {
+ this.jsonStream = jsonStream;
return this;
}
diff --git a/ebean-api/src/main/java/io/ebean/service/SpiJsonService.java b/ebean-api/src/main/java/io/ebean/service/SpiJsonService.java
index a7fb1753d..25eb68a95 100644
--- a/ebean-api/src/main/java/io/ebean/service/SpiJsonService.java
+++ b/ebean-api/src/main/java/io/ebean/service/SpiJsonService.java
@@ -1,8 +1,8 @@
package io.ebean.service;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonToken;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonReader.Token;
+import io.avaje.json.JsonWriter;
import java.io.IOException;
import java.io.Reader;
@@ -32,12 +32,12 @@ public interface SpiJsonService extends BootstrapService {
/**
* Write the nested Map/List as json to the jsonGenerator.
*/
- void write(Object object, JsonGenerator jsonGenerator) throws IOException;
+ void write(Object object, JsonWriter jsonGenerator) throws IOException;
/**
* Write the collection as json array to the jsonGenerator.
*/
- void writeCollection(Collection
-
- com.fasterxml.jackson.core
- jackson-core
- ${jackson.version}
- true
+ io.avaje
+ avaje-json-core
+ ${avaje-json-core.version}
diff --git a/ebean-core-json/src/main/java/io/ebeaninternal/json/DJsonService.java b/ebean-core-json/src/main/java/io/ebeaninternal/json/DJsonService.java
index f286bae4d..cbec38cd5 100644
--- a/ebean-core-json/src/main/java/io/ebeaninternal/json/DJsonService.java
+++ b/ebean-core-json/src/main/java/io/ebeaninternal/json/DJsonService.java
@@ -1,190 +1,129 @@
package io.ebeaninternal.json;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonToken;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonReader.Token;
+import io.avaje.json.JsonWriter;
import io.ebean.service.SpiJsonService;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
-import java.util.*;
+import java.util.Collection;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
/**
* Utility that converts between JSON content and simple java Maps/Lists.
*/
public final class DJsonService implements SpiJsonService {
- /**
- * Write the nested Map/List as json.
- */
@Override
public String write(Object object) throws IOException {
return EJsonWriter.write(object);
}
- /**
- * Write the nested Map/List as json to the writer.
- */
@Override
public void write(Object object, Writer writer) throws IOException {
EJsonWriter.write(object, writer);
}
- /**
- * Write the nested Map/List as json to the jsonGenerator.
- */
@Override
- public void write(Object object, JsonGenerator jsonGenerator) throws IOException {
- EJsonWriter.write(object, jsonGenerator);
+ public void write(Object object, JsonWriter jsonWriter) throws IOException {
+ EJsonWriter.write(object, jsonWriter);
}
- /**
- * Write the collection as json array to the jsonGenerator.
- */
@Override
- public void writeCollection(Collection collection, JsonGenerator jsonGenerator) throws IOException {
- EJsonWriter.writeCollection(collection, jsonGenerator);
+ public void writeCollection(Collection collection, JsonWriter jsonWriter) throws IOException {
+ EJsonWriter.writeCollection(collection, jsonWriter);
}
- /**
- * Parse the json and return as a Map additionally specifying if the returned map should be modify
- * aware meaning that it can detect when it has been modified.
- */
@Override
public Map parseObject(String json, boolean modifyAware) throws IOException {
return EJsonReader.parseObject(json, modifyAware);
}
- /**
- * Parse the json and return as a Map.
- */
@Override
public Map parseObject(String json) throws IOException {
return EJsonReader.parseObject(json);
}
- /**
- * Parse the json and return as a Map taking a reader.
- */
@Override
public Map parseObject(Reader reader, boolean modifyAware) throws IOException {
return EJsonReader.parseObject(reader, modifyAware);
}
- /**
- * Parse the json and return as a Map taking a reader.
- */
@Override
public Map parseObject(Reader reader) throws IOException {
return EJsonReader.parseObject(reader);
}
- /**
- * Parse the json and return as a Map taking a JsonParser.
- */
@Override
- public Map parseObject(JsonParser parser) throws IOException {
+ public Map parseObject(JsonReader parser) throws IOException {
return EJsonReader.parseObject(parser);
}
- /**
- * Parse the json and return as a Map taking a JsonParser and a starting token.
- *
- *
Used when the first token is checked to see if the value is null prior to calling this.
- */
@Override
- public Map parseObject(JsonParser parser, JsonToken token) throws IOException {
+ public Map parseObject(JsonReader parser, Token token) throws IOException {
return EJsonReader.parseObject(parser, token);
}
- /**
- * Parse the json and return as a modify aware List.
- */
@Override
public List parseList(String json, boolean modifyAware) throws IOException {
return EJsonReader.parseList(json, modifyAware);
}
- /**
- * Parse the json and return as a List.
- */
@Override
public List parseList(String json) throws IOException {
return EJsonReader.parseList(json);
}
- /**
- * Parse the json and return as a List taking a Reader.
- */
@Override
public List parseList(Reader reader) throws IOException {
return EJsonReader.parseList(reader);
}
- /**
- * Parse the json and return as a List taking a JsonParser.
- */
@Override
- public List parseList(JsonParser parser) throws IOException {
+ public List parseList(JsonReader parser) throws IOException {
return EJsonReader.parseList(parser, false);
}
- /**
- * Parse the json returning as a List taking into account the current token.
- */
@Override
@SuppressWarnings("unchecked")
- public List parseList(JsonParser parser, JsonToken currentToken) throws IOException {
+ public List parseList(JsonReader parser, Token currentToken) throws IOException {
return (List) EJsonReader.parse(parser, currentToken, false);
}
- /**
- * Parse the json and return as a List or Map.
- */
@Override
public Object parse(String json) throws IOException {
return EJsonReader.parse(json);
}
- /**
- * Parse the json and return as a List or Map.
- */
@Override
public Object parse(Reader reader) throws IOException {
return EJsonReader.parse(reader);
}
- /**
- * Parse the json and return as a List or Map.
- */
@Override
- public Object parse(JsonParser parser) throws IOException {
+ public Object parse(JsonReader parser) throws IOException {
return EJsonReader.parse(parser);
}
- /**
- * Parse the json returning a Set that might be modify aware.
- */
@Override
public Set parseSet(String json, boolean modifyAware) throws IOException {
List list = parseList(json, modifyAware);
if (list == null) {
return null;
}
-
if (modifyAware) {
return ((ModifyAwareList) list).asSet();
- } else {
- return new LinkedHashSet<>(list);
}
+ return new LinkedHashSet<>(list);
}
- /**
- * Parse the json returning as a Set taking into account the current token.
- */
@Override
- public Set parseSet(JsonParser parser, JsonToken currentToken) throws IOException {
+ public Set parseSet(JsonReader parser, Token currentToken) throws IOException {
return new LinkedHashSet<>(parseList(parser, currentToken));
}
}
diff --git a/ebean-core-json/src/main/java/io/ebeaninternal/json/EJsonReader.java b/ebean-core-json/src/main/java/io/ebeaninternal/json/EJsonReader.java
index 7c808979f..1d40f8f24 100644
--- a/ebean-core-json/src/main/java/io/ebeaninternal/json/EJsonReader.java
+++ b/ebean-core-json/src/main/java/io/ebeaninternal/json/EJsonReader.java
@@ -1,29 +1,25 @@
package io.ebeaninternal.json;
-import com.fasterxml.jackson.core.JsonFactory;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonToken;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonReader.Token;
+import io.avaje.json.stream.JsonStream;
import io.ebean.ModifyAwareType;
import java.io.IOException;
import java.io.Reader;
-import java.io.StringReader;
-import java.util.*;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
final class EJsonReader {
- static final JsonFactory json = new JsonFactory();
- private final JsonParser parser;
- private final boolean modifyAware;
- private final ModifyAwareFlag modifyAwareOwner;
- private int depth;
- private Stack stack;
- private Context currentContext;
+ private EJsonReader() {
+ }
- EJsonReader(JsonParser parser, boolean modifyAware) {
- this.parser = parser;
- this.modifyAware = modifyAware;
- this.modifyAwareOwner = modifyAware ? new ModifyAwareFlag() : null;
+ private static JsonReader reader(String content) {
+ return JsonStream.builder().build().reader(content);
}
@SuppressWarnings("unchecked")
@@ -47,12 +43,12 @@ final class EJsonReader {
}
@SuppressWarnings("unchecked")
- static Map parseObject(JsonParser parser) throws IOException {
+ static Map parseObject(JsonReader parser) throws IOException {
return (Map) parse(parser);
}
@SuppressWarnings("unchecked")
- static Map parseObject(JsonParser parser, JsonToken token) throws IOException {
+ static Map parseObject(JsonReader parser, Token token) throws IOException {
return (Map) parse(parser, token, false);
}
@@ -72,285 +68,137 @@ final class EJsonReader {
}
@SuppressWarnings("unchecked")
- static List parseList(JsonParser parser, boolean modifyAware) throws IOException {
- return (List) parse(parser, modifyAware);
+ static List parseList(JsonReader parser, boolean modifyAware) throws IOException {
+ return (List) parse(parser, null, modifyAware);
}
static Object parse(String json) throws IOException {
- if (json == null) {
- return null;
- }
- return parse(new StringReader(json));
+ return parseRawJson(json, null);
}
static Object parse(String json, boolean modifyAware) throws IOException {
- if (json == null) {
- return null;
- }
- return parse(new StringReader(json), modifyAware);
+ return parseRawJson(json, modifyAware ? new ModifyAwareFlag() : null);
}
static Object parse(Reader reader) throws IOException {
- return parse(json.createParser(reader));
+ return parseRawJson(readAll(reader), null);
}
static Object parse(Reader reader, boolean modifyAware) throws IOException {
- return parse(json.createParser(reader), modifyAware);
+ return parseRawJson(readAll(reader), modifyAware ? new ModifyAwareFlag() : null);
}
- static Object parse(JsonParser parser) throws IOException {
+ static Object parse(JsonReader parser) throws IOException {
return parse(parser, null, false);
}
- static Object parse(JsonParser parser, boolean modifyAware) throws IOException {
+ static Object parse(JsonReader parser, boolean modifyAware) throws IOException {
return parse(parser, null, modifyAware);
}
- static Object parse(JsonParser parser, JsonToken token, boolean modifyAware) throws IOException {
- return new EJsonReader(parser, modifyAware).parseJson(token);
- }
-
- private void startArray() {
- depth++;
- stack.push(currentContext);
- currentContext = modifyAware ? new ArrayContext(modifyAwareOwner) : new ArrayContext();
- }
-
- private void startObject() {
- depth++;
- stack.push(currentContext);
- currentContext = modifyAware ? new ObjectContext(modifyAwareOwner) : new ObjectContext();
- }
-
- private void endArray() {
- end();
- }
-
- private void endObject() {
- end();
- }
-
- private void end() {
- depth--;
- if (!stack.isEmpty()) {
- currentContext = stack.pop(currentContext);
- }
- if (modifyAwareOwner != null) {
- modifyAwareOwner.setMarkedDirty(false);
+ static Object parse(JsonReader parser, Token token, boolean modifyAware) throws IOException {
+ ModifyAwareType owner = modifyAware ? new ModifyAwareFlag() : null;
+ Token effectiveToken = token == null ? parser.currentToken() : token;
+ if (effectiveToken == null) {
+ return parseRawJson(parser.readRaw(), owner);
}
+ return parseValue(parser, effectiveToken, owner);
}
- private void setValue(Object value) {
- currentContext.setValue(value);
- }
-
- private void setValueNull() {
- currentContext.setValueNull();
- }
-
- private Object parseJson(JsonToken token) throws IOException {
-
+ private static Object parseValue(JsonReader parser, Token token, ModifyAwareType owner) throws IOException {
if (token == null) {
- token = parser.nextToken();
- // if it is a simple value just return it
- switch (token) {
- case VALUE_NULL:
+ token = parser.currentToken();
+ if (token == null) {
+ if (parser.isNullValue()) {
return null;
- case VALUE_FALSE:
- return Boolean.FALSE;
- case VALUE_TRUE:
- return Boolean.TRUE;
- case VALUE_STRING:
- return parser.getText();
- case VALUE_NUMBER_INT:
- return parser.getLongValue();
- case VALUE_NUMBER_FLOAT:
- return parser.getDecimalValue();
+ }
+ return parseRawJson(parser.readRaw(), owner);
}
}
-
- // it is a object or array, process the first JsonToken
- stack = new Stack();
- processJsonToken(token);
-
- // process the rest of the object or array
- while (depth > 0) {
- token = parser.nextToken();
- processJsonToken(token);
+ if (token == Token.BEGIN_OBJECT) {
+ return parseObjectValue(parser, owner);
}
-
- return currentContext.getValue();
+ if (token == Token.BEGIN_ARRAY) {
+ return parseArrayValue(parser, owner);
+ }
+ if (token == Token.NUMBER) {
+ BigDecimal value = parser.readDecimal();
+ return value.scale() <= 0 ? value.longValue() : value;
+ }
+ if (token == Token.STRING) {
+ return parser.readString();
+ }
+ if (token == Token.BOOLEAN) {
+ return parser.readBoolean();
+ }
+ if (token == Token.NULL) {
+ parser.isNullValue();
+ return null;
+ }
+ return parseRawJson(parser.readRaw(), owner);
}
- /**
- * Process the JsonToken for objects and arrays.
- */
- private void processJsonToken(JsonToken token) throws IOException {
- switch (token) {
- case START_ARRAY:
- startArray();
- break;
-
- case START_OBJECT:
- startObject();
- break;
-
- case FIELD_NAME:
- currentContext.setKey(parser.getCurrentName());
- break;
-
- case VALUE_STRING:
- setValue(parser.getValueAsString());
- break;
-
- case VALUE_NUMBER_INT:
- setValue(parser.getLongValue());
- break;
-
- case VALUE_NUMBER_FLOAT:
- setValue(parser.getDecimalValue());
- break;
-
- case VALUE_TRUE:
- setValue(Boolean.TRUE);
- break;
-
- case VALUE_FALSE:
- setValue(Boolean.FALSE);
- break;
-
- case VALUE_NULL:
- setValueNull();
- break;
-
- case END_OBJECT:
- endObject();
- break;
-
- case END_ARRAY:
- endArray();
- break;
-
- default:
- break;
+ private static Object parseRawJson(String json, ModifyAwareType owner) throws IOException {
+ if (json == null) {
+ return null;
}
+ String content = json.trim();
+ if (content.isEmpty()) {
+ return null;
+ }
+ JsonReader parser = reader(content);
+ Token token = parser.currentToken();
+ return parseValue(parser, token, owner);
}
- private static final class Stack {
+ private static String readAll(Reader reader) throws IOException {
+ StringBuilder builder = new StringBuilder();
+ char[] buffer = new char[2048];
+ int len;
+ while ((len = reader.read(buffer)) != -1) {
+ builder.append(buffer, 0, len);
+ }
+ return builder.toString();
+ }
- private Context head;
+ private static Map parseObjectValue(JsonReader parser, ModifyAwareType owner) throws IOException {
+ Map map = owner == null
+ ? new LinkedHashMap<>()
+ : new ModifyAwareMap<>(owner, new LinkedHashMap<>());
- private void push(Context context) {
- if (context != null) {
- context.next = head;
- head = context;
+ parser.beginObject();
+ while (parser.hasNextField()) {
+ String fieldName = parser.nextField();
+ map.put(fieldName, parseValue(parser, parser.currentToken(), owner));
+ if (owner != null) {
+ owner.setMarkedDirty(false);
}
}
+ parser.endObject();
+ if (owner != null) {
+ owner.setMarkedDirty(false);
+ }
+ return map;
+ }
- private Context pop(Context endingContext) {
- if (head == null) {
- throw new NoSuchElementException();
+ private static List parseArrayValue(JsonReader parser, ModifyAwareType owner) throws IOException {
+ List list = owner == null
+ ? new ArrayList<>()
+ : new ModifyAwareList<>(owner, new ArrayList<>());
+
+ parser.beginArray();
+ while (parser.hasNextElement()) {
+ Token elementToken = parser.currentToken();
+ Object elementValue = parseValue(parser, elementToken, owner);
+ list.add(elementValue);
+ if (owner != null) {
+ owner.setMarkedDirty(false);
}
- Context temp = head;
- head = head.next;
- temp.popContext(endingContext);
- return temp;
}
-
- private boolean isEmpty() {
- return head == null;
- }
- }
-
- private abstract static class Context {
- Context next;
-
- abstract void popContext(Context temp);
-
- abstract Object getValue();
-
- abstract void setValue(Object value);
-
- abstract void setKey(String key);
-
- abstract void setValueNull();
- }
-
- private static class ObjectContext extends Context {
-
- private final Map map;
-
- private String key;
-
- ObjectContext() {
- map = new LinkedHashMap<>();
- }
-
- ObjectContext(ModifyAwareType owner) {
- map = new ModifyAwareMap<>(owner, new LinkedHashMap<>());
- }
-
- @Override
- public void popContext(Context temp) {
- setValue(temp.getValue());
- }
-
- @Override
- Object getValue() {
- return map;
- }
-
- @Override
- void setValue(Object value) {
- map.put(key, value);
- }
-
- @Override
- void setKey(String key) {
- this.key = key;
- }
-
- @Override
- void setValueNull() {
- map.put(key, null);
- }
- }
-
- private static class ArrayContext extends Context {
-
- private final List values;
-
- ArrayContext() {
- values = new ArrayList<>();
- }
-
- ArrayContext(ModifyAwareType owner) {
- values = new ModifyAwareList<>(owner, new ArrayList<>());
- }
-
- @Override
- public void popContext(Context temp) {
- values.add(temp.getValue());
- }
-
- @Override
- Object getValue() {
- return values;
- }
-
- @Override
- void setValue(Object value) {
- values.add(value);
- }
-
- @Override
- void setValueNull() {
- // ignore
- }
-
- @Override
- void setKey(String key) {
- // not expected
+ parser.endArray();
+ if (owner != null) {
+ owner.setMarkedDirty(false);
}
+ return list;
}
}
diff --git a/ebean-core-json/src/main/java/io/ebeaninternal/json/EJsonWriter.java b/ebean-core-json/src/main/java/io/ebeaninternal/json/EJsonWriter.java
index ff73de8f9..46c7f4434 100644
--- a/ebean-core-json/src/main/java/io/ebeaninternal/json/EJsonWriter.java
+++ b/ebean-core-json/src/main/java/io/ebeaninternal/json/EJsonWriter.java
@@ -1,212 +1,149 @@
package io.ebeaninternal.json;
-import com.fasterxml.jackson.core.JsonFactory;
-import com.fasterxml.jackson.core.JsonGenerator;
+import io.avaje.json.stream.JsonStream;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.math.BigDecimal;
-import java.math.BigInteger;
import java.util.Collection;
-import java.util.Date;
+import java.util.Iterator;
import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
+/**
+ * Utility to write simple java Maps/Lists as JSON.
+ */
final class EJsonWriter {
- /**
- * Base jsonFactory implementation used when it is not passed in.
- */
- static final JsonFactory jsonFactory = new JsonFactory();
- private final JsonGenerator jsonGenerator;
+ private static final JsonStream JSON_STREAM = JsonStream.builder().build();
- private EJsonWriter(JsonGenerator jsonGenerator) {
- this.jsonGenerator = jsonGenerator;
+ private EJsonWriter() {
}
+ /**
+ * Convert object to Json content.
+ */
static String write(Object object) throws IOException {
- StringWriter writer = new StringWriter(200);
- write(object, writer).close();
+ StringWriter writer = new StringWriter();
+ write(object, writer);
return writer.toString();
}
- static JsonGenerator write(Object object, Writer writer) throws IOException {
- JsonGenerator generator = jsonFactory.createGenerator(writer);
- write(object, generator);
- generator.flush();
- return generator;
+ /**
+ * Convert object to Json content.
+ */
+ static io.avaje.json.JsonWriter write(Object object, Writer writer) throws IOException {
+ io.avaje.json.JsonWriter jsonWriter = JSON_STREAM.writer(writer);
+ jsonWriter.serializeNulls(true);
+ write(object, jsonWriter);
+ jsonWriter.flush();
+ return jsonWriter;
}
- static void write(Object object, JsonGenerator jsonGenerator) {
- new EJsonWriter(jsonGenerator).writeJson(object);
- }
-
- static void writeCollection(Collection collection, JsonGenerator jsonGenerator) throws IOException {
- new EJsonWriter(jsonGenerator).writeCollection(null, collection);
- }
-
- private void writeJson(Object object) {
- writeJson(null, object);
- }
-
- @SuppressWarnings("unchecked")
- private void writeJson(String name, Object object) {
- try {
- if (object == null) {
- writeNull(name);
-
- } else if (object instanceof Number) {
- writeNumber(name, (Number) object);
-
- } else if (object instanceof String) {
- writeString(name, (String) object);
-
- } else if (object instanceof Map) {
- writeMap(name, (Map) object);
-
- } else if (object instanceof Collection) {
- writeCollection(name, (Collection) object);
-
- } else if (object instanceof Boolean) {
- writeBoolean(name, (Boolean) object);
-
- } else if (object instanceof Date) {
- writeDate(name, (Date) object);
-
- } else if (object instanceof Map.Entry, ?>) {
- Map.Entry, ?> entry = (Map.Entry, ?>) object;
- writeJson(entry.getKey().toString(), entry.getValue());
-
- } else {
- writeString(name, object.toString());
- }
-
- } catch (IOException e) {
- throw new RuntimeException(e);
+ /**
+ * Convert object to Json content.
+ */
+ static void write(Object object, io.avaje.json.JsonWriter jsonWriter) throws IOException {
+ if (object == null) {
+ jsonWriter.nullValue();
+ return;
}
- }
-
- private void writeBoolean(String name, Boolean object) throws IOException {
- if (name == null) {
- jsonGenerator.writeBoolean(object);
- } else {
- jsonGenerator.writeBooleanField(name, object);
+ if (object instanceof String) {
+ jsonWriter.value((String) object);
+ return;
}
- }
-
- private void writeDate(String name, Date object) throws IOException {
- if (name == null) {
- jsonGenerator.writeNumber(object.getTime());
- } else {
- jsonGenerator.writeNumberField(name, object.getTime());
+ if (object instanceof Integer) {
+ jsonWriter.value((Integer) object);
+ return;
}
- }
-
- private void writeNumber(String name, Number object) throws IOException {
-
if (object instanceof Long) {
- writeLong(name, object);
-
- } else if (object instanceof Integer) {
- writeInteger(name, object);
-
- } else if (object instanceof Double) {
- writeDouble(name, object);
-
- } else if (object instanceof BigDecimal) {
- writeBigDecimal(name, object);
-
- } else if (object instanceof BigInteger) {
- writeBigInteger(name, object);
-
- } else {
- writeGeneralNumber(name, object);
+ jsonWriter.value((Long) object);
+ return;
}
+ if (object instanceof Double) {
+ jsonWriter.value((Double) object);
+ return;
+ }
+ if (object instanceof Float) {
+ jsonWriter.value((Float) object);
+ return;
+ }
+ if (object instanceof BigDecimal) {
+ jsonWriter.value((BigDecimal) object);
+ return;
+ }
+ if (object instanceof Boolean) {
+ jsonWriter.value((Boolean) object);
+ return;
+ }
+ if (object instanceof Map, ?>) {
+ writeMap((Map, ?>) object, jsonWriter);
+ return;
+ }
+ if (object instanceof Collection>) {
+ writeCollection((Collection>) object, jsonWriter);
+ return;
+ }
+
+ jsonWriter.value(object.toString());
}
- private void writeGeneralNumber(String name, Number object) throws IOException {
- writeBigDecimal(name, new BigDecimal(object.toString()));
+ /**
+ * Write map as Json content.
+ */
+ private static void writeMap(Map, ?> map, io.avaje.json.JsonWriter jsonWriter) throws IOException {
+ jsonWriter.beginObject();
+ for (Map.Entry, ?> entry : map.entrySet()) {
+ String fieldName = (String) entry.getKey();
+ Object value = entry.getValue();
+ jsonWriter.name(fieldName);
+ write(value, jsonWriter);
+ }
+ jsonWriter.endObject();
}
- private void writeBigDecimal(String name, Number object) throws IOException {
- if (name == null) {
- jsonGenerator.writeNumber((BigDecimal) object);
- } else {
- jsonGenerator.writeNumberField(name, (BigDecimal) object);
+ /**
+ * Write list as Json content.
+ */
+ static void writeCollection(Collection> list, io.avaje.json.JsonWriter jsonWriter) throws IOException {
+ jsonWriter.beginArray();
+ for (Object element : list) {
+ write(element, jsonWriter);
}
+ jsonWriter.endArray();
}
- private void writeBigInteger(String name, Number object) throws IOException {
- if (name == null) {
- jsonGenerator.writeNumber((BigInteger) object);
- } else {
- jsonGenerator.writeNumberField(name, object.longValue());
- }
+ /**
+ * Convert map to Json content.
+ */
+ static String write(Map map) throws IOException {
+ StringWriter writer = new StringWriter();
+ write(map, writer);
+ return writer.toString();
}
- private void writeDouble(String name, Number object) throws IOException {
- if (name == null) {
- jsonGenerator.writeNumber((Double) object);
- } else {
- jsonGenerator.writeNumberField(name, (Double) object);
- }
+ /**
+ * Convert map to Json content.
+ */
+ static io.avaje.json.JsonWriter write(Map map, Writer writer) throws IOException {
+ io.avaje.json.JsonWriter jsonWriter = JSON_STREAM.writer(writer);
+ jsonWriter.serializeNulls(true);
+ write(map, jsonWriter);
+ jsonWriter.flush();
+ return jsonWriter;
}
- private void writeLong(String name, Number object) throws IOException {
- if (name == null) {
- jsonGenerator.writeNumber((Long) object);
- } else {
- jsonGenerator.writeNumberField(name, (Long) object);
+ /**
+ * Convert map to Json content.
+ */
+ static void write(Map map, io.avaje.json.JsonWriter jsonWriter) throws IOException {
+ jsonWriter.beginObject();
+ Iterator> it = map.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry entry = it.next();
+ jsonWriter.name(entry.getKey());
+ write(entry.getValue(), jsonWriter);
}
- }
-
- private void writeInteger(String name, Number object) throws IOException {
- if (name == null) {
- jsonGenerator.writeNumber((Integer) object);
- } else {
- jsonGenerator.writeNumberField(name, (Integer) object);
- }
- }
-
- private void writeNull(String name) throws IOException {
- if (name == null) {
- jsonGenerator.writeNull();
- } else {
- jsonGenerator.writeNullField(name);
- }
- }
-
- private void writeString(String name, String object) throws IOException {
- if (name == null) {
- jsonGenerator.writeString(object);
- } else {
- jsonGenerator.writeStringField(name, object);
- }
- }
-
- private void writeCollection(String name, Collection collection) throws IOException {
- if (name != null) {
- jsonGenerator.writeFieldName(name);
- }
- jsonGenerator.writeStartArray();
- for (Object object : collection) {
- writeJson(null, object);
- }
- jsonGenerator.writeEndArray();
- }
-
- private void writeMap(String name, Map map) throws IOException {
-
- if (name != null) {
- jsonGenerator.writeFieldName(name);
- }
- jsonGenerator.writeStartObject();
- Set> entrySet = map.entrySet();
- for (Entry entry : entrySet) {
- writeJson(entry.getKey().toString(), entry.getValue());
- }
- jsonGenerator.writeEndObject();
+ jsonWriter.endObject();
}
}
diff --git a/ebean-core-json/src/main/java/module-info.java b/ebean-core-json/src/main/java/module-info.java
index b7561ed62..0845699bd 100644
--- a/ebean-core-json/src/main/java/module-info.java
+++ b/ebean-core-json/src/main/java/module-info.java
@@ -1,8 +1,7 @@
module io.ebean.core.json {
requires io.ebean.api;
-
- requires transitive com.fasterxml.jackson.core;
+ requires transitive io.avaje.json;
exports io.ebeaninternal.json to io.ebean.test, io.ebean.core;
provides io.ebean.service.BootstrapService with io.ebeaninternal.json.DJsonService;
diff --git a/ebean-core-type/pom.xml b/ebean-core-type/pom.xml
index 2adbb33df..0cebee48b 100644
--- a/ebean-core-type/pom.xml
+++ b/ebean-core-type/pom.xml
@@ -20,10 +20,9 @@
- com.fasterxml.jackson.core
- jackson-core
- ${jackson.version}
- true
+ io.avaje
+ avaje-json-core
+ ${avaje-json-core.version}
diff --git a/ebean-core-type/src/main/java/io/ebean/core/type/ScalarType.java b/ebean-core-type/src/main/java/io/ebean/core/type/ScalarType.java
index 9047befb0..31f49b7ad 100644
--- a/ebean-core-type/src/main/java/io/ebean/core/type/ScalarType.java
+++ b/ebean-core-type/src/main/java/io/ebean/core/type/ScalarType.java
@@ -1,7 +1,7 @@
package io.ebean.core.type;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonParser;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonWriter;
import io.ebean.text.StringFormatter;
import io.ebean.text.StringParser;
@@ -177,13 +177,44 @@ public interface ScalarType extends StringParser, StringFormatter, ScalarData
void writeData(DataOutput dataOutput, T value) throws IOException;
/**
- * Read the value from JsonParser.
+ * Read the value from JsonReader.
*/
- T jsonRead(JsonParser parser) throws IOException;
+ default T jsonRead(JsonReader parser) throws IOException {
+ JsonReader.Token token = parser.currentToken();
+ if (token == JsonReader.Token.NULL) {
+ parser.isNullValue();
+ return null;
+ }
+ if (token == JsonReader.Token.STRING) {
+ return parse(parser.readString());
+ }
+ return parse(parser.readRaw());
+ }
/**
- * Write the value to the JsonGenerator.
+ * Write the value to the JsonWriter.
*/
- void jsonWrite(JsonGenerator writer, T value) throws IOException;
+ default void jsonWrite(JsonWriter writer, T value) throws IOException {
+ if (value == null) {
+ writer.nullValue();
+ return;
+ }
+ String formatted = formatValue(value);
+ if (formatted == null) {
+ writer.nullValue();
+ return;
+ }
+ DocPropertyType docType = docType();
+ if (docType == DocPropertyType.OBJECT || docType == DocPropertyType.LIST || docType == DocPropertyType.ROOT || likelyRawJson(formatted)) {
+ writer.rawValue(formatted);
+ } else {
+ writer.value(formatted);
+ }
+ }
+
+ private static boolean likelyRawJson(String formatted) {
+ String trimmed = formatted.trim();
+ return !trimmed.isEmpty() && (trimmed.charAt(0) == '{' || trimmed.charAt(0) == '[');
+ }
}
diff --git a/ebean-core-type/src/main/java/io/ebean/core/type/ScalarTypeBaseDate.java b/ebean-core-type/src/main/java/io/ebean/core/type/ScalarTypeBaseDate.java
index 5d76cfade..66550a4ed 100644
--- a/ebean-core-type/src/main/java/io/ebean/core/type/ScalarTypeBaseDate.java
+++ b/ebean-core-type/src/main/java/io/ebean/core/type/ScalarTypeBaseDate.java
@@ -1,8 +1,8 @@
package io.ebean.core.type;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonToken;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonReader.Token;
+import io.avaje.json.JsonWriter;
import io.ebean.config.JsonConfig;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.DataReader;
@@ -83,20 +83,31 @@ public abstract class ScalarTypeBaseDate extends ScalarTypeBase {
}
@Override
- public T jsonRead(JsonParser parser) throws IOException {
- if (JsonToken.VALUE_NUMBER_INT == parser.getCurrentToken()) {
- return convertFromMillis(parser.getLongValue());
- } else {
- return convertFromDate(Date.valueOf(parser.getText()));
+ public T jsonRead(JsonReader parser) throws IOException {
+ Token token = parser.currentToken();
+ if (Token.NUMBER == token) {
+ return convertFromMillis(parser.readLong());
}
+ if (Token.STRING == token) {
+ return convertFromDate(Date.valueOf(parser.readString()));
+ }
+
+ String raw = parser.readRaw();
+ if (raw == null || "null".equals(raw)) {
+ return null;
+ }
+ if (raw.length() > 1 && raw.charAt(0) == '"' && raw.charAt(raw.length() - 1) == '"') {
+ return convertFromDate(Date.valueOf(raw.substring(1, raw.length() - 1)));
+ }
+ return convertFromMillis(Long.parseLong(raw));
}
@Override
- public void jsonWrite(JsonGenerator writer, T value) throws IOException {
+ public void jsonWrite(JsonWriter writer, T value) throws IOException {
if (mode == JsonConfig.Date.ISO8601) {
- writer.writeString(toIsoFormat(value));
+ writer.value(toIsoFormat(value));
} else {
- writer.writeNumber(convertToMillis(value));
+ writer.value(convertToMillis(value));
}
}
diff --git a/ebean-core-type/src/main/java/io/ebean/core/type/ScalarTypeBaseDateTime.java b/ebean-core-type/src/main/java/io/ebean/core/type/ScalarTypeBaseDateTime.java
index 0ee2cb82f..95e7a9a89 100644
--- a/ebean-core-type/src/main/java/io/ebean/core/type/ScalarTypeBaseDateTime.java
+++ b/ebean-core-type/src/main/java/io/ebean/core/type/ScalarTypeBaseDateTime.java
@@ -1,7 +1,8 @@
package io.ebean.core.type;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonParser;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonReader.Token;
+import io.avaje.json.JsonWriter;
import io.ebean.config.JsonConfig;
import java.io.DataInput;
@@ -99,35 +100,53 @@ public abstract class ScalarTypeBaseDateTime extends ScalarTypeBase {
}
@Override
- public T jsonRead(JsonParser parser) throws IOException {
- switch (parser.getCurrentToken()) {
- case VALUE_NUMBER_INT: {
- return convertFromMillis(parser.getLongValue());
- }
- case VALUE_NUMBER_FLOAT: {
- BigDecimal value = parser.getDecimalValue();
- Timestamp timestamp = ScalarTypeUtils.toTimestamp(value);
- return convertFromTimestamp(timestamp);
- }
- default: {
- return fromJsonISO8601(parser.getText());
- }
+ public T jsonRead(JsonReader parser) throws IOException {
+ Token token = parser.currentToken();
+ if (token == Token.NUMBER) {
+ return readNumber(parser.readDecimal());
}
+ if (token == Token.STRING) {
+ return fromStringValue(parser.readString());
+ }
+
+ String raw = parser.readRaw();
+ if (raw == null || "null".equals(raw)) {
+ return null;
+ }
+ if (raw.length() > 1 && raw.charAt(0) == '"' && raw.charAt(raw.length() - 1) == '"') {
+ return fromStringValue(raw.substring(1, raw.length() - 1));
+ }
+ return readNumber(new BigDecimal(raw));
+ }
+
+ private T fromStringValue(String value) {
+ if (value.indexOf('-') == -1 && Character.isDigit(value.charAt(0))) {
+ return readNumber(new BigDecimal(value));
+ }
+ return fromJsonISO8601(value);
+ }
+
+ private T readNumber(BigDecimal value) {
+ if (value.scale() <= 0) {
+ return convertFromMillis(value.longValue());
+ }
+ Timestamp timestamp = ScalarTypeUtils.toTimestamp(value);
+ return convertFromTimestamp(timestamp);
}
@Override
- public void jsonWrite(JsonGenerator writer, T value) throws IOException {
+ public void jsonWrite(JsonWriter writer, T value) throws IOException {
switch (mode) {
case ISO8601: {
- writer.writeString(toJsonISO8601(value));
+ writer.value(toJsonISO8601(value));
break;
}
case NANOS: {
- writer.writeNumber(toJsonNanos(value));
+ writer.value(toJsonNanos(value));
break;
}
default: {
- writer.writeNumber(convertToMillis(value));
+ writer.value(convertToMillis(value));
}
}
}
diff --git a/ebean-core-type/src/main/java/io/ebean/core/type/ScalarTypeBaseVarchar.java b/ebean-core-type/src/main/java/io/ebean/core/type/ScalarTypeBaseVarchar.java
index 99c83561b..f0646ee13 100644
--- a/ebean-core-type/src/main/java/io/ebean/core/type/ScalarTypeBaseVarchar.java
+++ b/ebean-core-type/src/main/java/io/ebean/core/type/ScalarTypeBaseVarchar.java
@@ -1,7 +1,7 @@
package io.ebean.core.type;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonParser;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonWriter;
import java.io.DataInput;
import java.io.DataOutput;
@@ -104,13 +104,16 @@ public abstract class ScalarTypeBaseVarchar extends ScalarTypeBase {
}
@Override
- public T jsonRead(JsonParser parser) throws IOException {
- return parse(parser.getValueAsString());
+ public T jsonRead(JsonReader parser) throws IOException {
+ if (parser.isNullValue()) {
+ return null;
+ }
+ return parse(parser.readString());
}
@Override
- public void jsonWrite(JsonGenerator writer, T value) throws IOException {
- writer.writeString(format(value));
+ public void jsonWrite(JsonWriter writer, T value) throws IOException {
+ writer.value(format(value));
}
@Override
diff --git a/ebean-core-type/src/main/java/module-info.java b/ebean-core-type/src/main/java/module-info.java
index 88be6d462..9c48ef295 100644
--- a/ebean-core-type/src/main/java/module-info.java
+++ b/ebean-core-type/src/main/java/module-info.java
@@ -4,8 +4,7 @@ module io.ebean.core.type {
requires transitive java.sql;
requires transitive io.ebean.api;
+ requires transitive io.avaje.json;
requires static org.postgresql.jdbc;
- requires static com.fasterxml.jackson.core;
-
}
diff --git a/ebean-core/pom.xml b/ebean-core/pom.xml
index d993d56a8..33094da19 100644
--- a/ebean-core/pom.xml
+++ b/ebean-core/pom.xml
@@ -138,14 +138,6 @@
-
-
- com.fasterxml.jackson.core
- jackson-core
- ${jackson.version}
- true
-
-
com.fasterxml.jackson.corejackson-databind
diff --git a/ebean-core/src/main/java/io/ebeaninternal/api/SpiJsonContext.java b/ebean-core/src/main/java/io/ebeaninternal/api/SpiJsonContext.java
index 2700ed60e..a868c17b9 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/api/SpiJsonContext.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/api/SpiJsonContext.java
@@ -1,6 +1,6 @@
package io.ebeaninternal.api;
-import com.fasterxml.jackson.core.JsonGenerator;
+import io.avaje.json.JsonWriter;
import io.ebean.plugin.BeanType;
import io.ebean.text.json.JsonContext;
import io.ebean.text.json.JsonWriteOptions;
@@ -17,7 +17,7 @@ public interface SpiJsonContext extends JsonContext {
/**
* Create a Json Writer for writing beans as JSON.
*/
- SpiJsonWriter createJsonWriter(JsonGenerator gen, JsonWriteOptions options);
+ SpiJsonWriter createJsonWriter(JsonWriter gen, JsonWriteOptions options);
/**
* Create a Json Writer for writing beans as JSON supplying a writer.
diff --git a/ebean-core/src/main/java/io/ebeaninternal/api/json/SpiJsonReader.java b/ebean-core/src/main/java/io/ebeaninternal/api/json/SpiJsonReader.java
index 613b105cc..125c933d9 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/api/json/SpiJsonReader.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/api/json/SpiJsonReader.java
@@ -1,8 +1,8 @@
package io.ebeaninternal.api.json;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.ObjectMapper;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonReader.Token;
import io.ebean.bean.EntityBean;
import io.ebean.bean.PersistenceContext;
import io.ebeaninternal.server.deploy.BeanDescriptor;
@@ -14,7 +14,9 @@ public interface SpiJsonReader {
PersistenceContext persistenceContext();
- SpiJsonReader forJson(JsonParser moreJson);
+ SpiJsonReader forJson(JsonReader moreJson);
+
+ SpiJsonReader forJson(String moreJson);
void persistenceContextPut(Object beanId, T currentBean);
@@ -22,9 +24,9 @@ public interface SpiJsonReader {
ObjectMapper mapper();
- JsonParser parser();
+ JsonReader parser();
- JsonToken nextToken() throws IOException;
+ Token nextToken() throws IOException;
void pushPath(String path);
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/changelog/ChangeJsonBuilder.java b/ebean-core/src/main/java/io/ebeaninternal/server/changelog/ChangeJsonBuilder.java
index 5d71023b8..dae1a1138 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/changelog/ChangeJsonBuilder.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/changelog/ChangeJsonBuilder.java
@@ -1,7 +1,7 @@
package io.ebeaninternal.server.changelog;
-import com.fasterxml.jackson.core.JsonFactory;
-import com.fasterxml.jackson.core.JsonGenerator;
+import io.avaje.json.JsonWriter;
+import io.avaje.json.stream.JsonStream;
import io.ebean.event.changelog.BeanChange;
import io.ebean.event.changelog.ChangeSet;
import io.ebean.event.changelog.ChangeType;
@@ -15,13 +15,13 @@ import java.util.Map;
*/
final class ChangeJsonBuilder {
- private final JsonFactory jsonFactory = new JsonFactory();
+ private final JsonStream jsonStream = JsonStream.builder().build();
/**
* Write the bean change as JSON.
*/
void writeBeanJson(Writer writer, BeanChange bean, ChangeSet changeSet) throws IOException {
- try (JsonGenerator generator = jsonFactory.createGenerator(writer)) {
+ try (JsonWriter generator = jsonStream.writer(writer)) {
writeBeanChange(generator, bean, changeSet);
generator.flush();
}
@@ -30,58 +30,67 @@ final class ChangeJsonBuilder {
/**
* Write the bean change as JSON document containing the transaction header details.
*/
- private void writeBeanChange(JsonGenerator gen, BeanChange bean, ChangeSet changeSet) throws IOException {
- gen.writeStartObject();
- gen.writeNumberField("ts", bean.getEventTime());
- gen.writeStringField("change", bean.getEvent().getCode());
- gen.writeStringField("type", bean.getType());
- gen.writeStringField("id", bean.getId().toString());
+ private void writeBeanChange(JsonWriter gen, BeanChange bean, ChangeSet changeSet) {
+ gen.beginObject();
+ gen.name("ts");
+ gen.value(bean.getEventTime());
+ gen.name("change");
+ gen.value(bean.getEvent().getCode());
+ gen.name("type");
+ gen.value(bean.getType());
+ gen.name("id");
+ gen.value(bean.getId().toString());
if (bean.getTenantId() != null) {
- gen.writeStringField("tenantId", bean.getTenantId().toString());
+ gen.name("tenantId");
+ gen.value(bean.getTenantId().toString());
}
writeBeanTransactionDetails(gen, changeSet);
writeBeanValues(gen, bean);
- gen.writeEndObject();
+ gen.endObject();
}
/**
* Denormalise by writing the transaction header details.
*/
- private void writeBeanTransactionDetails(JsonGenerator gen, ChangeSet changeSet) throws IOException {
+ private void writeBeanTransactionDetails(JsonWriter gen, ChangeSet changeSet) {
String source = changeSet.getSource();
if (source != null) {
- gen.writeStringField("source", source);
+ gen.name("source");
+ gen.value(source);
}
String userId = changeSet.getUserId();
if (userId != null) {
- gen.writeStringField("userId", userId);
+ gen.name("userId");
+ gen.value(userId);
}
String userIpAddress = changeSet.getUserIpAddress();
if (userIpAddress != null) {
- gen.writeStringField("userIpAddress", userIpAddress);
+ gen.name("userIpAddress");
+ gen.value(userIpAddress);
}
Map userContext = changeSet.getUserContext();
if (userContext != null && !userContext.isEmpty()) {
- gen.writeObjectFieldStart("userContext");
+ gen.name("userContext");
+ gen.beginObject();
for (Map.Entry entry : userContext.entrySet()) {
- gen.writeStringField(entry.getKey(), entry.getValue());
+ gen.name(entry.getKey());
+ gen.value(entry.getValue());
}
- gen.writeEndObject();
+ gen.endObject();
}
}
/**
* For insert and update write the new/old values.
*/
- private void writeBeanValues(JsonGenerator gen, BeanChange bean) throws IOException {
+ private void writeBeanValues(JsonWriter gen, BeanChange bean) {
if (bean.getEvent() != ChangeType.DELETE) {
- gen.writeFieldName("data");
- gen.writeRaw(":");
- gen.writeRaw(bean.getData());
+ gen.name("data");
+ gen.rawValue(bean.getData());
String oldData = bean.getOldData();
if (oldData != null) {
- gen.writeRaw(",\"oldData\":");
- gen.writeRaw(oldData);
+ gen.name("oldData");
+ gen.rawValue(oldData);
}
}
}
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/core/InternalConfiguration.java b/ebean-core/src/main/java/io/ebeaninternal/server/core/InternalConfiguration.java
index e90716ccd..158080b28 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/core/InternalConfiguration.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/core/InternalConfiguration.java
@@ -1,6 +1,6 @@
package io.ebeaninternal.server.core;
-import com.fasterxml.jackson.core.JsonFactory;
+import io.avaje.json.stream.JsonStream;
import io.ebean.DatabaseBuilder;
import io.ebean.ExpressionFactory;
import io.ebean.annotation.Platform;
@@ -89,7 +89,7 @@ public final class InternalConfiguration {
private final boolean jacksonCorePresent;
private final ExpressionFactory expressionFactory;
private final SpiBackgroundExecutor backgroundExecutor;
- private final JsonFactory jsonFactory;
+ private final JsonStream jsonStream;
private final DocStoreFactory docStoreFactory;
private final List plugins = new ArrayList<>();
private final MultiValueBind multiValueBind;
@@ -108,7 +108,7 @@ public final class InternalConfiguration {
this.tableModState = new TableModState();
this.logManager = initLogManager();
this.docStoreFactory = initDocStoreFactory(service(DocStoreFactory.class));
- this.jsonFactory = config.getJsonFactory();
+ this.jsonStream = config.getJsonStream();
this.clusterManager = clusterManager;
this.backgroundExecutor = backgroundExecutor;
this.bootupClasses = bootupClasses;
@@ -292,7 +292,7 @@ public final class InternalConfiguration {
}
SpiJsonContext createJsonContext(SpiEbeanServer server) {
- return jacksonCorePresent ? new DJsonContext(server, jsonFactory, typeManager) : null;
+ return jacksonCorePresent ? new DJsonContext(server, jsonStream, typeManager) : null;
}
AutoTuneService createAutoTuneService(SpiEbeanServer server) {
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanChangeJson.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanChangeJson.java
index 66b3faa45..9fc447c76 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanChangeJson.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanChangeJson.java
@@ -2,8 +2,11 @@ package io.ebeaninternal.server.deploy;
import io.ebean.PersistenceIOException;
import io.ebean.bean.BeanDiffVisitor;
+import io.ebean.config.JsonConfig;
import io.ebeaninternal.api.json.SpiJsonWriter;
+import io.ebeaninternal.server.json.WriteJson;
import io.ebeaninternal.server.util.ArrayStack;
+import io.avaje.json.stream.JsonStream;
import java.io.IOException;
import java.io.StringWriter;
@@ -13,26 +16,18 @@ import java.io.StringWriter;
*/
final class BeanChangeJson implements BeanDiffVisitor {
- private final StringWriter newData;
- private final StringWriter oldData;
- private final SpiJsonWriter newJson;
- private final SpiJsonWriter oldJson;
+ private final StringWriter data;
+ private final SpiJsonWriter json;
+ private final boolean writeNew;
private final ArrayStack> stack = new ArrayStack<>();
private BeanDescriptor> descriptor;
- BeanChangeJson(BeanDescriptor> descriptor, boolean statelessUpdate) {
+ BeanChangeJson(BeanDescriptor> descriptor, boolean writeNew) {
this.descriptor = descriptor;
- this.newData = new StringWriter(200);
- this.newJson = descriptor.createJsonWriter(newData);
- newJson.writeStartObject();
- if (statelessUpdate) {
- this.oldJson = null;
- this.oldData = null;
- } else {
- this.oldData = new StringWriter(200);
- this.oldJson = descriptor.createJsonWriter(oldData);
- oldJson.writeStartObject();
- }
+ this.writeNew = writeNew;
+ this.data = new StringWriter(200);
+ this.json = new WriteJson(JsonStream.builder().build().writer(data), JsonConfig.Include.ALL);
+ json.writeStartObject();
}
@Override
@@ -40,10 +35,7 @@ final class BeanChangeJson implements BeanDiffVisitor {
try {
BeanProperty prop = descriptor.propertiesIndex[position];
if (prop.isDbUpdatable()) {
- prop.jsonWriteValue(newJson, newVal);
- if (oldJson != null) {
- prop.jsonWriteValue(oldJson, oldVal);
- }
+ prop.jsonWriteValue(json, writeNew ? newVal : oldVal);
}
} catch (IOException e) {
throw new PersistenceIOException(e);
@@ -55,18 +47,12 @@ final class BeanChangeJson implements BeanDiffVisitor {
stack.push(descriptor);
BeanPropertyAssocOne> embedded = (BeanPropertyAssocOne>)descriptor.propertiesIndex[position];
descriptor = embedded.targetDescriptor();
- newJson.writeStartObject(embedded.name());
- if (oldJson != null) {
- oldJson.writeStartObject(embedded.name());
- }
+ json.writeStartObject(embedded.name());
}
@Override
public void visitPop() {
- newJson.writeEndObject();
- if (oldJson != null) {
- oldJson.writeEndObject();
- }
+ json.writeEndObject();
descriptor = stack.pop();
}
@@ -75,28 +61,14 @@ final class BeanChangeJson implements BeanDiffVisitor {
*/
void flush() {
try {
- newJson.writeEndObject();
- newJson.flush();
- if (oldJson != null) {
- oldJson.writeEndObject();
- oldJson.flush();
- }
+ json.writeEndObject();
+ json.flush();
} catch (IOException e) {
throw new PersistenceIOException(e);
}
}
- /**
- * Return the new values JSON.
- */
- String newJson() {
- return newData.toString();
- }
-
- /**
- * Return the old values JSON.
- */
- String oldJson() {
- return oldData == null ? null : oldData.toString();
+ String json() {
+ return data.toString();
}
}
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptor.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptor.java
index 5dfdd705b..16da6b307 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptor.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptor.java
@@ -792,10 +792,17 @@ public class BeanDescriptor implements BeanType, STreeType, SpiBeanType {
*/
private BeanChange updateBeanChange(PersistRequestBean request) {
try {
- BeanChangeJson changeJson = new BeanChangeJson(this, request.isStatelessUpdate());
- request.intercept().addDirtyPropertyValues(changeJson);
- changeJson.flush();
- return beanChange(ChangeType.UPDATE, request.beanId(), changeJson.newJson(), changeJson.oldJson());
+ BeanChangeJson newValues = new BeanChangeJson(this, true);
+ request.intercept().addDirtyPropertyValues(newValues);
+ newValues.flush();
+ String oldData = null;
+ if (!request.isStatelessUpdate()) {
+ BeanChangeJson oldValues = new BeanChangeJson(this, false);
+ request.intercept().addDirtyPropertyValues(oldValues);
+ oldValues.flush();
+ oldData = oldValues.json();
+ }
+ return beanChange(ChangeType.UPDATE, request.beanId(), newValues.json(), oldData);
} catch (RuntimeException e) {
log.log(ERROR, "Failed to write ChangeLog entry for update", e);
return null;
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorElementEmbeddedMap.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorElementEmbeddedMap.java
index ecb283e5c..04dbaec5e 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorElementEmbeddedMap.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorElementEmbeddedMap.java
@@ -1,6 +1,6 @@
package io.ebeaninternal.server.deploy;
-import com.fasterxml.jackson.core.JsonParser;
+import io.avaje.json.JsonReader;
import io.ebean.bean.EntityBean;
import io.ebean.core.type.ScalarType;
import io.ebeaninternal.api.json.SpiJsonReader;
@@ -49,25 +49,25 @@ class BeanDescriptorElementEmbeddedMap extends BeanDescriptorElementEmbedded<
@Override
public Object jsonReadCollection(SpiJsonReader readJson, EntityBean parentBean) throws IOException {
- JsonParser parser = readJson.parser();
+ JsonReader parser = readJson.parser();
ElementCollector add = elementHelp.createCollector();
- do {
- String fieldName = parser.nextFieldName();
- if (fieldName == null) {
- break;
- }
+ parser.beginObject();
+ while (parser.hasNextField()) {
+ String fieldName = parser.nextField();
if (stringKey) {
- parser.nextToken();
Object val = readJsonElement(readJson, null, null); // CHECKME: Update existing map entry here?
add.addKeyValue(fieldName, val);
} else {
- parser.nextFieldName();
+ parser.beginObject();
+ parser.nextField();
Object key = scalarTypeKey.jsonRead(parser);
- parser.nextFieldName();
+ parser.nextField();
Object val = readJsonElement(readJson, null, null); // CHECKME: Update existing map entry here?
+ parser.endObject();
add.addKeyValue(key, val);
}
- } while (true);
+ }
+ parser.endObject();
return add.collection();
}
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorElementScalar.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorElementScalar.java
index 0242c993f..d50b9c234 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorElementScalar.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorElementScalar.java
@@ -1,7 +1,6 @@
package io.ebeaninternal.server.deploy;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonToken;
+import io.avaje.json.JsonReader;
import io.ebean.PersistenceIOException;
import io.ebean.SqlUpdate;
import io.ebean.bean.EntityBean;
@@ -40,15 +39,13 @@ class BeanDescriptorElementScalar extends BeanDescriptorElement {
@Override
public Object jsonReadCollection(SpiJsonReader readJson, EntityBean parentBean) throws IOException {
- JsonParser parser = readJson.parser();
+ JsonReader parser = readJson.parser();
ElementCollector add = elementHelp.createCollector();
- do {
- JsonToken token = parser.nextToken();
- if (JsonToken.VALUE_NULL == token || JsonToken.END_ARRAY == token) {
- break;
- }
+ parser.beginArray();
+ while (parser.hasNextElement()) {
add.addElement(scalarType.jsonRead(parser));
- } while (true);
+ }
+ parser.endArray();
return add.collection();
}
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorElementScalarMap.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorElementScalarMap.java
index d5b8d91a9..4de87ebdb 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorElementScalarMap.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorElementScalarMap.java
@@ -1,6 +1,6 @@
package io.ebeaninternal.server.deploy;
-import com.fasterxml.jackson.core.JsonParser;
+import io.avaje.json.JsonReader;
import io.ebean.bean.EntityBean;
import io.ebean.core.type.ScalarType;
import io.ebeaninternal.api.json.SpiJsonReader;
@@ -49,25 +49,25 @@ class BeanDescriptorElementScalarMap extends BeanDescriptorElement {
@Override
public Object jsonReadCollection(SpiJsonReader readJson, EntityBean parentBean) throws IOException {
- JsonParser parser = readJson.parser();
+ JsonReader parser = readJson.parser();
ElementCollector add = elementHelp.createCollector();
- do {
- String fieldName = parser.nextFieldName();
- if (fieldName == null) {
- break;
- }
+ parser.beginObject();
+ while (parser.hasNextField()) {
+ String fieldName = parser.nextField();
if (stringKey) {
- parser.nextToken();
Object val = scalarTypeVal.jsonRead(parser);
add.addKeyValue(fieldName, val);
} else {
- parser.nextFieldName();
+ parser.beginObject();
+ parser.nextField();
Object key = scalarTypeKey.jsonRead(parser);
- parser.nextFieldName();
+ parser.nextField();
Object val = scalarTypeVal.jsonRead(parser);
+ parser.endObject();
add.addKeyValue(key, val);
}
- } while (true);
+ }
+ parser.endObject();
return add.collection();
}
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorJsonHelp.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorJsonHelp.java
index 720ef92ca..46587cc89 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorJsonHelp.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorJsonHelp.java
@@ -1,10 +1,7 @@
package io.ebeaninternal.server.deploy;
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonToken;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonReader.Token;
import io.ebean.bean.EntityBean;
import io.ebean.text.json.EJson;
import io.ebeaninternal.api.json.SpiJsonReader;
@@ -34,7 +31,8 @@ final class BeanDescriptorJsonHelp {
InheritInfo localInheritInfo = inheritInfo.readType(bean.getClass());
String discValue = localInheritInfo.getDiscriminatorStringValue();
String discColumn = localInheritInfo.getDiscriminatorColumn();
- writeJson.gen().writeStringField(discColumn, discValue);
+ writeJson.gen().name(discColumn);
+ writeJson.gen().value(discValue);
localInheritInfo.desc().jsonWriteProperties(writeJson, bean);
}
writeJson.writeEndObject();
@@ -66,44 +64,38 @@ final class BeanDescriptorJsonHelp {
@SuppressWarnings("unchecked")
T jsonRead(SpiJsonReader jsonRead, String path, boolean withInheritance, T target) throws IOException {
- JsonParser parser = jsonRead.parser();
- //noinspection StatementWithEmptyBody
- if (parser.getCurrentToken() == JsonToken.START_OBJECT) {
- // start object token read by Jackson already
- } else {
- // check for null or start object
- JsonToken token = parser.nextToken();
- if (JsonToken.VALUE_NULL == token || JsonToken.END_ARRAY == token) {
- return null;
- }
- if (JsonToken.START_OBJECT != token) {
- throw new JsonParseException(parser, "Unexpected token " + token + " - expecting start_object", parser.getCurrentLocation());
- }
+ JsonReader parser = jsonRead.parser();
+ if (parser.isNullValue()) {
+ return null;
+ }
+ Token token = parser.currentToken();
+ if (token != Token.BEGIN_OBJECT) {
+ throw new IllegalStateException("Unexpected token " + token + " - expecting BEGIN_OBJECT at: " + parser.location());
}
if (desc.inheritInfo == null || !withInheritance) {
return jsonReadObject(jsonRead, path, target);
}
- ObjectNode node = jsonRead.mapper().readTree(parser);
- if (node.isNull()) {
+ Map node = EJson.parseObject(parser);
+ if (node == null) {
return null;
}
- JsonParser newParser = node.traverse();
- SpiJsonReader newReader = jsonRead.forJson(newParser);
// check for the discriminator value to determine the correct sub type
String discColumn = inheritInfo.getRoot().getDiscriminatorColumn();
- JsonNode discNode = node.get(discColumn);
- if (discNode == null || discNode.isNull()) {
+ Object discValue = node.get(discColumn);
+ String rawObject = EJson.write(node);
+ SpiJsonReader newReader = jsonRead.forJson(rawObject);
+ if (discValue == null) {
if (!desc.isAbstractType()) {
return desc.jsonReadObject(newReader, path, target);
}
String msg = "Error reading inheritance discriminator - expected [" + discColumn + "] but no json key?";
- throw new JsonParseException(newParser, msg, parser.getCurrentLocation());
+ throw new IllegalStateException(msg);
}
- BeanDescriptor inheritDesc = (BeanDescriptor) inheritInfo.readType(discNode.asText()).desc();
+ BeanDescriptor inheritDesc = (BeanDescriptor) inheritInfo.readType(String.valueOf(discValue)).desc();
return inheritDesc.jsonReadObject(newReader, path, target);
}
@@ -124,35 +116,30 @@ final class BeanDescriptorJsonHelp {
if (path != null) {
readJson.pushPath(path);
}
+ JsonReader parser = readJson.parser();
+ parser.beginObject();
+
// unmapped properties, send to JsonReadBeanVisitor later
Map unmappedProperties = null;
- do {
- JsonParser parser = readJson.parser();
- JsonToken event = parser.nextToken();
- if (JsonToken.FIELD_NAME == event) {
- String key = parser.getCurrentName();
- BeanProperty p = desc.beanProperty(key);
- if (p != null) {
- if (p.isVersion() && readJson.update() ) {
- // skip version prop during update
- p.jsonRead(readJson);
- } else {
- p.jsonRead(readJson, bean);
- }
+ while (parser.hasNextField()) {
+ String key = parser.nextField();
+ BeanProperty p = desc.beanProperty(key);
+ if (p != null) {
+ if (p.isVersion() && readJson.update()) {
+ // skip version prop during update
+ p.jsonRead(readJson);
} else {
- // read an unmapped property
- if (unmappedProperties == null) {
- unmappedProperties = new LinkedHashMap<>();
- }
- unmappedProperties.put(key, EJson.parse(parser));
+ p.jsonRead(readJson, bean);
}
- } else if (JsonToken.END_OBJECT == event) {
- break;
} else {
- throw new RuntimeException("Unexpected token " + event + " - expecting key or end_object at: " + parser.getCurrentLocation());
+ // read an unmapped property
+ if (unmappedProperties == null) {
+ unmappedProperties = new LinkedHashMap<>();
+ }
+ unmappedProperties.put(key, EJson.parse(parser));
}
-
- } while (true);
+ }
+ parser.endObject();
if (unmappedProperties != null) {
desc.setUnmappedJson(bean, unmappedProperties);
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanProperty.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanProperty.java
index 2c6443b77..9e9579637 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanProperty.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanProperty.java
@@ -1,6 +1,7 @@
package io.ebeaninternal.server.deploy;
-import com.fasterxml.jackson.core.JsonToken;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonReader.Token;
import io.ebean.DataIntegrityException;
import io.ebean.ModifyAwareType;
import io.ebean.ValuePair;
@@ -1437,14 +1438,14 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
}
public Object jsonRead(SpiJsonReader ctx) throws IOException {
- JsonToken event = ctx.nextToken();
- if (JsonToken.VALUE_NULL == event) {
+ JsonReader parser = ctx.parser();
+ if (parser.isNullValue()) {
return null;
} else {
// expect to read non-null json value
Object objValue;
if (scalarType != null) {
- objValue = scalarType.jsonRead(ctx.parser());
+ objValue = scalarType.jsonRead(parser);
} else {
try {
objValue = ctx.readValueUsingObjectMapper(propertyType);
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyAssocMany.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyAssocMany.java
index 2374b24ec..6c82b9dc3 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyAssocMany.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyAssocMany.java
@@ -1,15 +1,14 @@
package io.ebeaninternal.server.deploy;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonToken;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonReader.Token;
import io.ebean.SqlUpdate;
import io.ebean.Transaction;
import io.ebean.bean.BeanCollection;
import io.ebean.bean.BeanCollection.ModifyListenMode;
import io.ebean.bean.BeanCollectionAdd;
import io.ebean.bean.EntityBean;
+import io.ebean.bean.EntityBeanIntercept;
import io.ebean.bean.PersistenceContext;
import io.ebean.plugin.PropertyAssocMany;
import io.ebean.text.PathProperties;
@@ -1043,9 +1042,8 @@ public class BeanPropertyAssocMany extends BeanPropertyAssoc implements ST
*/
private Object jsonReadCollection(String json) throws IOException {
SpiJsonReader ctx = descriptor.createJsonReader(json);
- JsonParser parser = ctx.parser();
- JsonToken event = parser.nextToken();
- if (JsonToken.VALUE_NULL == event) {
+ JsonReader parser = ctx.parser();
+ if (parser.isNullValue()) {
return null;
}
return jsonReadCollection(ctx, null, null);
@@ -1068,20 +1066,18 @@ public class BeanPropertyAssocMany extends BeanPropertyAssoc implements ST
BeanCollection> collection = createEmpty(parentBean);
BeanCollectionAdd add = beanCollectionAdd(collection);
Map existingBeans = extractBeans(targets);
- do {
-
+ JsonReader parser = readJson.parser();
+ parser.beginArray();
+ while (parser.hasNextElement()) {
EntityBean detailBean = getDetailBean(readJson, existingBeans);
- if (detailBean == null) {
- // read the entire array
- break;
+ if (detailBean != null) {
+ add.addEntityBean(detailBean);
+ if (parentBean != null && childMasterProperty != null) {
+ // bind detail bean back to master via mappedBy property
+ childMasterProperty.setValue(detailBean, parentBean);
+ }
}
- add.addEntityBean(detailBean);
-
- if (parentBean != null && childMasterProperty != null) {
- // bind detail bean back to master via mappedBy property
- childMasterProperty.setValue(detailBean, parentBean);
- }
- } while (true);
+ }
return collection;
}
@@ -1092,18 +1088,79 @@ public class BeanPropertyAssocMany extends BeanPropertyAssoc implements ST
BeanProperty idProperty = targetDescriptor.idProperty();
if (targets == null || idProperty == null) {
return (EntityBean) targetDescriptor.jsonRead(readJson, name, null);
- } else {
- JsonToken token = readJson.parser().nextToken();
- if (JsonToken.VALUE_NULL == token || JsonToken.END_ARRAY == token) {
- return null;
- }
- // extract the id. We have to buffer the JSON;
- ObjectNode node = readJson.mapper().readTree(readJson.parser());
- SpiJsonReader jsonReader = readJson.forJson(node.traverse());
- JsonNode idNode = node.get(idProperty.name());
- Object id = idNode == null ? null : idProperty.jsonRead(readJson.forJson(idNode.traverse()));
- return (EntityBean) targetDescriptor.jsonRead(jsonReader, name, targets.get(id));
}
+ /// ROB Checkme
+ JsonReader parser = readJson.parser();
+ if (parser.isNullValue()) {
+ return null;
+ }
+ EntityBean incomingBean = (EntityBean) targetDescriptor.jsonRead(readJson, name, null);
+ Object id = idProperty.getValue(incomingBean);
+ EntityBean existingBean = (EntityBean) targets.get(id);
+ if (existingBean == null) {
+ return incomingBean;
+ }
+ mergeLoadedBean(targetDescriptor, incomingBean, existingBean);
+ return existingBean;
+ }
+
+ private void mergeLoadedBean(BeanDescriptor> descriptor, EntityBean incomingBean, EntityBean existingBean) {
+ EntityBeanIntercept incomingIntercept = incomingBean._ebean_getIntercept();
+ for (BeanProperty property : descriptor.propertiesBaseScalar()) {
+ if (incomingIntercept.isLoadedProperty(property.propertyIndex())) {
+ property.setValueIntercept(existingBean, property.getValue(incomingBean));
+ }
+ }
+ for (BeanPropertyAssocMany> property : descriptor.propertiesMany()) {
+ if (incomingIntercept.isLoadedProperty(property.propertyIndex())) {
+ Object mergedValue = mergeLoadedMany(property, property.getValue(incomingBean), property.getValue(existingBean));
+ property.setValueIntercept(existingBean, mergedValue);
+ }
+ }
+ }
+
+ private Object mergeLoadedMany(BeanPropertyAssocMany> property, Object incomingValue, Object existingValue) {
+ if (!(incomingValue instanceof Collection>)) {
+ return incomingValue;
+ }
+ if (!(existingValue instanceof Collection>)) {
+ return incomingValue;
+ }
+ Collection> incomingCollection = (Collection>) incomingValue;
+ Collection> existingCollection = (Collection>) existingValue;
+ BeanProperty idProperty = property.targetDescriptor.idProperty();
+ if (idProperty == null) {
+ return incomingValue;
+ }
+
+ Map existingById = new LinkedHashMap<>();
+ for (Object existingElement : existingCollection) {
+ if (existingElement instanceof EntityBean) {
+ EntityBean existingBean = (EntityBean) existingElement;
+ Object id = idProperty.getValue(existingBean);
+ if (id != null) {
+ existingById.put(id, existingBean);
+ }
+ }
+ }
+
+ BeanCollection> mergedCollection = property.createEmpty(null);
+ BeanCollectionAdd add = property.beanCollectionAdd(mergedCollection);
+ for (Object incomingElement : incomingCollection) {
+ if (!(incomingElement instanceof EntityBean)) {
+ continue;
+ }
+ EntityBean incomingBean = (EntityBean) incomingElement;
+ Object id = idProperty.getValue(incomingBean);
+ EntityBean existingBean = id == null ? null : existingById.get(id);
+ if (existingBean == null) {
+ add.addEntityBean(incomingBean);
+ } else {
+ mergeLoadedBean(property.targetDescriptor, incomingBean, existingBean);
+ add.addEntityBean(existingBean);
+ }
+ }
+ return mergedCollection;
}
/**
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyAssocManyJsonHelp.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyAssocManyJsonHelp.java
index 4bc7307fe..d22b18f8c 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyAssocManyJsonHelp.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyAssocManyJsonHelp.java
@@ -1,8 +1,7 @@
package io.ebeaninternal.server.deploy;
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonToken;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonReader.Token;
import io.ebean.bean.EntityBean;
import io.ebeaninternal.api.json.SpiJsonReader;
@@ -38,17 +37,17 @@ class BeanPropertyAssocManyJsonHelp {
if (!this.many.jsonDeserialize) {
return;
}
- JsonParser parser = readJson.parser();
- JsonToken event = parser.nextToken();
- if (JsonToken.VALUE_NULL == event) {
+ JsonReader parser = readJson.parser();
+ if (parser.isNullValue()) {
return;
}
if (many.isTransient()) {
jsonReadTransientUsingObjectMapper(readJson, parentBean);
return;
}
- if (JsonToken.START_ARRAY != event && JsonToken.START_OBJECT != event) {
- throw new JsonParseException(parser, "Unexpected token " + event + " - expecting start array or object");
+ Token event = parser.currentToken();
+ if (Token.BEGIN_ARRAY != event && Token.BEGIN_OBJECT != event) {
+ throw new IllegalStateException("Unexpected token " + event + " - expecting start array or object");
}
if (readJson.update()) {
many.setValueIntercept(parentBean, many.jsonReadCollection(readJson, parentBean, many.getValue(parentBean)));
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyAssocManyJsonTransient.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyAssocManyJsonTransient.java
index ae82bd7c6..92d58688c 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyAssocManyJsonTransient.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyAssocManyJsonTransient.java
@@ -29,11 +29,11 @@ class BeanPropertyAssocManyJsonTransient {
TypeFactory typeFactory = mapper.getTypeFactory();
JavaType target = typeFactory.constructType(many.targetType());
MapType jacksonType = typeFactory.constructMapType(LinkedHashMap.class, TypeFactory.unknownType(), target);
- value = mapper.readValue(readJson.parser(), jacksonType);
+ value = mapper.readValue(readJson.parser().readRaw(), jacksonType);
} else {
// read list or set using Jackson object mapper
CollectionType jacksonType = mapper.getTypeFactory().constructCollectionType(manyType.getCollectionType(), many.targetType());
- value = mapper.readValue(readJson.parser(), jacksonType);
+ value = mapper.readValue(readJson.parser().readRaw(), jacksonType);
}
many.setValue(parentBean, value);
}
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/json/DJsonBeanReader.java b/ebean-core/src/main/java/io/ebeaninternal/server/json/DJsonBeanReader.java
index f1b92a78b..08add2b91 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/json/DJsonBeanReader.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/json/DJsonBeanReader.java
@@ -1,6 +1,6 @@
package io.ebeaninternal.server.json;
-import com.fasterxml.jackson.core.JsonParser;
+import io.avaje.json.JsonReader;
import io.ebean.PersistenceIOException;
import io.ebean.bean.PersistenceContext;
import io.ebean.text.json.JsonBeanReader;
@@ -45,7 +45,7 @@ public final class DJsonBeanReader implements JsonBeanReader {
}
@Override
- public JsonBeanReader forJson(JsonParser moreJson) {
+ public JsonBeanReader forJson(JsonReader moreJson) {
return new DJsonBeanReader<>(desc, readJson.forJson(moreJson));
}
}
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/json/DJsonContext.java b/ebean-core/src/main/java/io/ebeaninternal/server/json/DJsonContext.java
index 39b80344b..6e9017540 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/json/DJsonContext.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/json/DJsonContext.java
@@ -1,12 +1,9 @@
package io.ebeaninternal.server.json;
-import com.fasterxml.jackson.core.JsonFactory;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonToken;
-import com.fasterxml.jackson.core.PrettyPrinter;
-import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonReader.Token;
+import io.avaje.json.JsonWriter;
+import io.avaje.json.stream.JsonStream;
import io.ebean.FetchPath;
import io.ebean.bean.EntityBean;
import io.ebean.config.JsonConfig;
@@ -28,7 +25,6 @@ import io.ebeaninternal.util.ParamTypeHelper.TypeInfo;
import java.io.IOException;
import java.io.Reader;
-import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Type;
@@ -45,30 +41,22 @@ import java.util.Set;
*/
public final class DJsonContext implements SpiJsonContext {
- private static final PrettyPrinter PRETTY_PRINTER = new Pretty();
-
private final SpiEbeanServer server;
- private final JsonFactory jsonFactory;
+ private final JsonStream jsonStream;
private final Object defaultObjectMapper;
private final JsonConfig.Include defaultInclude;
private final DJsonScalar jsonScalar;
- private static class Pretty extends DefaultPrettyPrinter {
- Pretty() {
- _objectFieldValueSeparatorWithSpaces = ": ";
- }
- }
-
- public DJsonContext(SpiEbeanServer server, JsonFactory jsonFactory, TypeManager typeManager) {
+ public DJsonContext(SpiEbeanServer server, JsonStream jsonStream, TypeManager typeManager) {
this.server = server;
- this.jsonFactory = (jsonFactory != null) ? jsonFactory : new JsonFactory();
+ this.jsonStream = jsonStream;
this.defaultObjectMapper = this.server.config().getObjectMapper();
this.defaultInclude = this.server.config().getJsonInclude();
this.jsonScalar = new DJsonScalar(typeManager);
}
@Override
- public void writeScalar(JsonGenerator generator, Object scalarValue) throws IOException {
+ public void writeScalar(JsonWriter generator, Object scalarValue) throws IOException {
jsonScalar.write(generator, scalarValue);
}
@@ -78,31 +66,34 @@ public final class DJsonContext implements SpiJsonContext {
}
@Override
- public JsonGenerator createGenerator(Writer writer) throws JsonIOException {
+ public JsonWriter createGenerator(Writer writer) throws JsonIOException {
+ JsonWriter jsonWriter = stream().writer(writer);
+ jsonWriter.serializeNulls(defaultInclude == JsonConfig.Include.ALL);
+ jsonWriter.serializeEmpty(defaultInclude != JsonConfig.Include.NON_EMPTY);
+ return jsonWriter;
+ }
+
+ @Override
+ public JsonReader createParser(Reader reader) throws JsonIOException {
try {
- return jsonFactory.createGenerator(writer);
+ return createParser(readAll(reader));
} catch (IOException e) {
throw new JsonIOException(e);
}
}
- @Override
- public JsonParser createParser(Reader reader) throws JsonIOException {
- try {
- return jsonFactory.createParser(reader);
- } catch (IOException e) {
- throw new JsonIOException(e);
- }
+ private JsonStream stream() {
+ return (jsonStream != null) ? jsonStream : JsonStream.builder().build();
}
@Override
public T toBean(Class cls, String json) throws JsonIOException {
- return toBean(cls, new StringReader(json));
+ return toBean(cls, createParser(json));
}
@Override
public T toBean(Class cls, String json, JsonReadOptions options) throws JsonIOException {
- return toBean(cls, new StringReader(json), options);
+ return toBean(cls, createParser(json), options);
}
@Override
@@ -116,15 +107,15 @@ public final class DJsonContext implements SpiJsonContext {
}
@Override
- public T toBean(Class cls, JsonParser parser) throws JsonIOException {
+ public T toBean(Class cls, JsonReader parser) throws JsonIOException {
return toBean(cls, parser, null);
}
@Override
- public T toBean(Class cls, JsonParser parser, JsonReadOptions options) throws JsonIOException {
+ public T toBean(Class cls, JsonReader parser, JsonReadOptions options) throws JsonIOException {
BeanDescriptor desc = getDescriptor(cls);
try {
- return desc.jsonRead(new ReadJson(desc, parser, options, determineObjectMapper(options), false), null, null);
+ return desc.jsonRead(new ReadJson(desc, parser, options, determineObjectMapper(options), false, stream()), null, null);
} catch (IOException e) {
throw new JsonIOException(e);
}
@@ -132,12 +123,12 @@ public final class DJsonContext implements SpiJsonContext {
@Override
public void toBean(T target, String json) throws JsonIOException {
- toBean(target, new StringReader(json));
+ toBean(target, createParser(json));
}
@Override
public void toBean(T target, String json, JsonReadOptions options) throws JsonIOException {
- toBean(target, new StringReader(json), options);
+ toBean(target, createParser(json), options);
}
@Override
@@ -151,42 +142,42 @@ public final class DJsonContext implements SpiJsonContext {
}
@Override
- public void toBean(T target, JsonParser parser) throws JsonIOException {
+ public void toBean(T target, JsonReader parser) throws JsonIOException {
toBean(target, parser, null);
}
@SuppressWarnings("unchecked")
@Override
- public void toBean(T target, JsonParser parser, JsonReadOptions options) throws JsonIOException {
+ public void toBean(T target, JsonReader parser, JsonReadOptions options) throws JsonIOException {
BeanDescriptor desc = (BeanDescriptor) getDescriptor(target.getClass());
try {
- desc.jsonRead(new ReadJson(desc, parser, options, determineObjectMapper(options), target != null), null, target);
+ desc.jsonRead(new ReadJson(desc, parser, options, determineObjectMapper(options), target != null, stream()), null, target);
} catch (IOException e) {
throw new JsonIOException(e);
}
}
@Override
- public DJsonBeanReader createBeanReader(Class cls, JsonParser parser, JsonReadOptions options) throws JsonIOException {
+ public DJsonBeanReader createBeanReader(Class cls, JsonReader parser, JsonReadOptions options) throws JsonIOException {
BeanDescriptor desc = getDescriptor(cls);
- return new DJsonBeanReader<>(desc, new ReadJson(desc, parser, options, determineObjectMapper(options), false));
+ return new DJsonBeanReader<>(desc, new ReadJson(desc, parser, options, determineObjectMapper(options), false, stream()));
}
@Override
- public DJsonBeanReader createBeanReader(BeanType beanType, JsonParser parser, JsonReadOptions options) throws JsonIOException {
+ public DJsonBeanReader createBeanReader(BeanType beanType, JsonReader parser, JsonReadOptions options) throws JsonIOException {
BeanDescriptor desc = (BeanDescriptor) beanType;
- SpiJsonReader readJson = new ReadJson(desc, parser, options, determineObjectMapper(options), false);
+ SpiJsonReader readJson = new ReadJson(desc, parser, options, determineObjectMapper(options), false, stream());
return new DJsonBeanReader<>(desc, readJson);
}
@Override
public List toList(Class cls, String json) throws JsonIOException {
- return toList(cls, new StringReader(json));
+ return toList(cls, createParser(json));
}
@Override
public List toList(Class cls, String json, JsonReadOptions options) throws JsonIOException {
- return toList(cls, new StringReader(json), options);
+ return toList(cls, createParser(json), options);
}
@Override
@@ -200,35 +191,30 @@ public final class DJsonContext implements SpiJsonContext {
}
@Override
- public List toList(Class cls, JsonParser src) throws JsonIOException {
+ public List toList(Class cls, JsonReader src) throws JsonIOException {
return toList(cls, src, null);
}
@Override
- public List toList(Class cls, JsonParser src, JsonReadOptions options) throws JsonIOException {
+ public List toList(Class cls, JsonReader src, JsonReadOptions options) throws JsonIOException {
BeanDescriptor desc = getDescriptor(cls);
- SpiJsonReader readJson = new ReadJson(desc, src, options, determineObjectMapper(options), false);
+ SpiJsonReader readJson = new ReadJson(desc, src, options, determineObjectMapper(options), false, stream());
try {
-
- JsonToken currentToken = src.getCurrentToken();
- if (currentToken != JsonToken.START_ARRAY) {
- JsonToken event = src.nextToken();
- if (event != JsonToken.START_ARRAY) {
- throw new JsonParseException(src, "Expecting start_array event but got " + event);
- }
+ if (src.isNullValue()) {
+ return null;
+ }
+ Token currentToken = src.currentToken();
+ if (currentToken != Token.BEGIN_ARRAY) {
+ throw new JsonIOException("Expecting BEGIN_ARRAY but got " + currentToken);
}
-
List list = new ArrayList<>();
- do {
- // CHECKME: Should we update the list
+ src.beginArray();
+ while (src.hasNextElement()) {
T bean = desc.jsonRead(readJson, null, null);
- if (bean == null) {
- break;
- } else {
+ if (bean != null) {
list.add(bean);
}
- } while (true);
-
+ }
return list;
} catch (IOException e) {
throw new JsonIOException(e);
@@ -237,7 +223,7 @@ public final class DJsonContext implements SpiJsonContext {
@Override
public Object toObject(Type genericType, String json) throws JsonIOException {
- return toObject(genericType, createParser(new StringReader(json)));
+ return toObject(genericType, createParser(json));
}
@Override
@@ -245,8 +231,22 @@ public final class DJsonContext implements SpiJsonContext {
return toObject(genericType, createParser(json));
}
+ private JsonReader createParser(String json) {
+ return stream().reader(json);
+ }
+
+ private String readAll(Reader reader) throws IOException {
+ StringBuilder builder = new StringBuilder();
+ char[] buffer = new char[2048];
+ int len;
+ while ((len = reader.read(buffer)) != -1) {
+ builder.append(buffer, 0, len);
+ }
+ return builder.toString();
+ }
+
@Override
- public Object toObject(Type genericType, JsonParser jsonParser) throws JsonIOException {
+ public Object toObject(Type genericType, JsonReader jsonParser) throws JsonIOException {
TypeInfo info = ParamTypeHelper.getTypeInfo(genericType);
ManyType manyType = info.getManyType();
switch (manyType) {
@@ -262,19 +262,19 @@ public final class DJsonContext implements SpiJsonContext {
}
@Override
- public void toJson(Object value, JsonGenerator generator) throws JsonIOException {
+ public void toJson(Object value, JsonWriter generator) throws JsonIOException {
// generator passed in so don't close it
toJsonNoClose(value, generator, null);
}
@Override
- public void toJson(Object value, JsonGenerator generator, FetchPath fetchPath) throws JsonIOException {
+ public void toJson(Object value, JsonWriter generator, FetchPath fetchPath) throws JsonIOException {
// generator passed in so don't close it
toJsonNoClose(value, generator, JsonWriteOptions.pathProperties(fetchPath));
}
@Override
- public void toJson(Object o, JsonGenerator generator, JsonWriteOptions options) throws JsonIOException {
+ public void toJson(Object o, JsonWriter generator, JsonWriteOptions options) throws JsonIOException {
// generator passed in so don't close it
toJsonNoClose(o, generator, options);
}
@@ -303,9 +303,9 @@ public final class DJsonContext implements SpiJsonContext {
}
/**
- * Write to the JsonGenerator and close when complete.
+ * Write to the JsonWriter and close when complete.
*/
- private void toJsonWithClose(Object o, JsonGenerator generator, JsonWriteOptions options) throws JsonIOException {
+ private void toJsonWithClose(Object o, JsonWriter generator, JsonWriteOptions options) throws JsonIOException {
try {
toJsonInternal(o, generator, options);
generator.close();
@@ -315,9 +315,9 @@ public final class DJsonContext implements SpiJsonContext {
}
/**
- * Write to the JsonGenerator and without closing it (as it was created externally).
+ * Write to the JsonWriter and without closing it (as it was created externally).
*/
- private void toJsonNoClose(Object o, JsonGenerator generator, JsonWriteOptions options) throws JsonIOException {
+ private void toJsonNoClose(Object o, JsonWriter generator, JsonWriteOptions options) throws JsonIOException {
try {
toJsonInternal(o, generator, options);
} catch (IOException e) {
@@ -342,9 +342,9 @@ public final class DJsonContext implements SpiJsonContext {
private String toJsonString(Object value, JsonWriteOptions options, boolean pretty) throws JsonIOException {
StringWriter writer = new StringWriter(500);
- try (JsonGenerator gen = createGenerator(writer)) {
+ try (JsonWriter gen = createGenerator(writer)) {
if (pretty) {
- gen.setPrettyPrinter(PRETTY_PRINTER);
+ gen.pretty(true);
}
toJsonInternal(value, gen, options);
} catch (IOException e) {
@@ -354,29 +354,23 @@ public final class DJsonContext implements SpiJsonContext {
}
@SuppressWarnings("unchecked")
- private void toJsonInternal(Object value, JsonGenerator gen, JsonWriteOptions options) throws IOException {
+ private void toJsonInternal(Object value, JsonWriter gen, JsonWriteOptions options) throws IOException {
if (value == null) {
- gen.writeNull();
+ gen.nullValue();
} else if (value instanceof Number) {
- gen.writeNumber(((Number) value).doubleValue());
+ gen.jsonValue(value);
} else if (value instanceof Boolean) {
- gen.writeBoolean((Boolean) value);
+ gen.value((Boolean) value);
} else if (value instanceof String) {
- gen.writeString((String) value);
-
- // } else if (o instanceof JsonElement) {
-
+ gen.value((String) value);
} else if (value instanceof Map, ?>) {
toJsonFromMap((Map) value, gen, options);
-
} else if (value instanceof Collection>) {
toJsonFromCollection((Collection>) value, null, gen, options);
-
} else if (value instanceof EntityBean) {
BeanDescriptor> d = getDescriptor(value.getClass());
WriteJson writeJson = createWriteJson(gen, options);
d.jsonWrite(writeJson, (EntityBean) value, null);
-
} else {
jsonScalar.write(gen, value);
}
@@ -385,8 +379,8 @@ public final class DJsonContext implements SpiJsonContext {
@Override
public SpiJsonReader createJsonRead(BeanType> beanType, String json) {
BeanDescriptor> desc = (BeanDescriptor>) beanType;
- JsonParser parser = createParser(new StringReader(json));
- return new ReadJson(desc, parser, null, defaultObjectMapper, false);
+ JsonReader parser = createParser(json);
+ return new ReadJson(desc, parser, null, defaultObjectMapper, false, stream());
}
@Override
@@ -395,11 +389,11 @@ public final class DJsonContext implements SpiJsonContext {
}
@Override
- public SpiJsonWriter createJsonWriter(JsonGenerator gen, JsonWriteOptions options) {
+ public SpiJsonWriter createJsonWriter(JsonWriter gen, JsonWriteOptions options) {
return createWriteJson(gen, options);
}
- private WriteJson createWriteJson(JsonGenerator gen, JsonWriteOptions options) {
+ private WriteJson createWriteJson(JsonWriter gen, JsonWriteOptions options) {
FetchPath pathProps = (options == null) ? null : options.getPathProperties();
Map> visitors = (options == null) ? null : options.getVisitorMap();
return new WriteJson(server,
@@ -411,46 +405,50 @@ public final class DJsonContext implements SpiJsonContext {
options == null || options.isIncludeLoadedImplicit());
}
- private void toJsonFromCollection(Collection collection, String key, JsonGenerator gen, JsonWriteOptions options) throws IOException {
+ private void toJsonFromCollection(Collection collection, String key, JsonWriter gen, JsonWriteOptions options) throws IOException {
if (key != null) {
- gen.writeFieldName(key);
+ gen.name(key);
}
- gen.writeStartArray();
+ gen.beginArray();
WriteJson writeJson = createWriteJson(gen, options);
for (T bean : collection) {
- BeanDescriptor> d = getDescriptor(bean.getClass());
- d.jsonWrite(writeJson, (EntityBean) bean, null);
+ if (bean == null) {
+ gen.nullValue();
+ } else if (bean instanceof EntityBean) {
+ BeanDescriptor> d = getDescriptor(bean.getClass());
+ d.jsonWrite(writeJson, (EntityBean) bean, null);
+ } else {
+ EJson.write(bean, gen);
+ }
}
- gen.writeEndArray();
+ gen.endArray();
}
- private void toJsonFromMap(Map map, JsonGenerator gen, JsonWriteOptions options) throws IOException {
+ private void toJsonFromMap(Map map, JsonWriter gen, JsonWriteOptions options) throws IOException {
Set> entrySet = map.entrySet();
Iterator> it = entrySet.iterator();
WriteJson writeJson = createWriteJson(gen, options);
- gen.writeStartObject();
+ gen.beginObject();
while (it.hasNext()) {
Entry entry = it.next();
String key = entry.getKey().toString();
Object value = entry.getValue();
if (value == null) {
- gen.writeNullField(key);
+ gen.name(key);
+ gen.nullValue();
+ } else if (value instanceof Collection>) {
+ toJsonFromCollection((Collection>) value, key, gen, options);
+ } else if (value instanceof EntityBean) {
+ BeanDescriptor> d = getDescriptor(value.getClass());
+ d.jsonWrite(writeJson, (EntityBean) value, key);
} else {
- if (value instanceof Collection>) {
- toJsonFromCollection((Collection>) value, key, gen, options);
-
- } else if (value instanceof EntityBean) {
- BeanDescriptor> d = getDescriptor(value.getClass());
- d.jsonWrite(writeJson, (EntityBean) value, key);
-
- } else {
- EJson.write(entry, gen);
- }
+ gen.name(key);
+ EJson.write(value, gen);
}
}
- gen.writeEndObject();
+ gen.endObject();
}
/**
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/json/DJsonScalar.java b/ebean-core/src/main/java/io/ebeaninternal/server/json/DJsonScalar.java
index cd3420773..d18e96a34 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/json/DJsonScalar.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/json/DJsonScalar.java
@@ -1,6 +1,6 @@
package io.ebeaninternal.server.json;
-import com.fasterxml.jackson.core.JsonGenerator;
+import io.avaje.json.JsonWriter;
import io.ebean.core.type.ScalarType;
import io.ebeaninternal.server.type.TypeManager;
@@ -19,21 +19,18 @@ public final class DJsonScalar {
}
@SuppressWarnings({ "unchecked", "rawtypes" })
- public void write(JsonGenerator gen, Object value) throws IOException {
+ public void write(JsonWriter gen, Object value) throws IOException {
if (value instanceof String) {
- gen.writeString((String) value);
+ gen.value((String) value);
} else if (value instanceof List) {
// expected for @DbArray values
List list = (List)value;
- gen.writeRaw('[');
+ gen.beginArray();
for (int i = 0; i < list.size(); i++) {
- if (i > 0) {
- gen.writeRaw(',');
- }
write(gen, list.get(i));
}
- gen.writeRaw(']');
+ gen.endArray();
} else {
ScalarType scalarType = typeManager.type(value.getClass());
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/json/ReadJson.java b/ebean-core/src/main/java/io/ebeaninternal/server/json/ReadJson.java
index ab9100c9f..181810c35 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/json/ReadJson.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/json/ReadJson.java
@@ -1,8 +1,10 @@
package io.ebeaninternal.server.json;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.ObjectMapper;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonReader.Token;
+import io.avaje.json.stream.BufferRecycleStrategy;
+import io.avaje.json.stream.JsonStream;
import io.ebean.bean.EntityBean;
import io.ebean.bean.EntityBeanIntercept;
import io.ebean.bean.PersistenceContext;
@@ -22,8 +24,9 @@ import java.util.Map;
*/
public final class ReadJson implements SpiJsonReader {
+ private final JsonStream jsonStream;
private final BeanDescriptor> rootDesc;
- private final JsonParser parser;
+ private final JsonReader parser;
private final PathStack pathStack;
/**
* Map of the JsonReadBeanVisitor keyed by path.
@@ -38,9 +41,10 @@ public final class ReadJson implements SpiJsonReader {
/**
* Construct with parser and readOptions.
*/
- public ReadJson(BeanDescriptor> desc, JsonParser parser, JsonReadOptions readOptions, Object objectMapper, boolean update) {
+ public ReadJson(BeanDescriptor> desc, JsonReader parser, JsonReadOptions readOptions, Object objectMapper, boolean update, JsonStream jsonStream) {
this.rootDesc = desc;
this.parser = parser;
+ this.jsonStream = jsonStream;
this.objectMapper = objectMapper;
this.persistenceContext = initPersistenceContext(readOptions);
this.loadContext = initLoadContext(desc, readOptions);
@@ -54,7 +58,8 @@ public final class ReadJson implements SpiJsonReader {
/**
* Construct when transferring load context, persistence context, object mapper etc to a new ReadJson instance.
*/
- private ReadJson(JsonParser moreJson, ReadJson source) {
+ private ReadJson(JsonReader moreJson, ReadJson source) {
+ this.jsonStream = source.jsonStream;
this.parser = moreJson;
this.rootDesc = source.rootDesc;
this.pathStack = source.pathStack;
@@ -91,13 +96,22 @@ public final class ReadJson implements SpiJsonReader {
}
/**
- * Return a new instance of ReadJson using the existing context but with a new JsonParser.
+ * Return a new instance of ReadJson using the existing context but with a new JsonReader.
*/
@Override
- public SpiJsonReader forJson(JsonParser moreJson) {
+ public SpiJsonReader forJson(JsonReader moreJson) {
return new ReadJson(moreJson, this);
}
+ @Override
+ public SpiJsonReader forJson(String moreJson) {
+ JsonReader nestedReader = JsonStream.builder()
+ .bufferRecycling(BufferRecycleStrategy.NO_RECYCLING)
+ .build()
+ .reader(moreJson);
+ return new ReadJson(nestedReader, this);
+ }
+
/**
* Add the bean to the persistence context.
*/
@@ -152,19 +166,19 @@ public final class ReadJson implements SpiJsonReader {
}
/**
- * Return the JsonParser.
+ * Return the JsonReader.
*/
@Override
- public JsonParser parser() {
+ public JsonReader parser() {
return parser;
}
/**
- * Return the next JsonToken from the underlying parser.
+ * Return the current token from the underlying parser.
*/
@Override
- public JsonToken nextToken() throws IOException {
- return parser.nextToken();
+ public Token nextToken() throws IOException {
+ return parser.currentToken();
}
/**
@@ -209,7 +223,7 @@ public final class ReadJson implements SpiJsonReader {
*/
@Override
public Object readValueUsingObjectMapper(Class> propertyType) throws IOException {
- return mapper().readValue(parser, propertyType);
+ return mapper().readValue(parser.readRaw(), propertyType);
}
/**
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/json/WriteJson.java b/ebean-core/src/main/java/io/ebeaninternal/server/json/WriteJson.java
index f5b583822..b11242d52 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/json/WriteJson.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/json/WriteJson.java
@@ -1,7 +1,7 @@
package io.ebeaninternal.server.json;
-import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
+import io.avaje.json.JsonWriter;
import io.ebean.FetchPath;
import io.ebean.bean.EntityBean;
import io.ebean.config.JsonConfig;
@@ -24,7 +24,7 @@ import java.util.Set;
public final class WriteJson implements SpiJsonWriter {
private final SpiEbeanServer server;
- private final JsonGenerator generator;
+ private final JsonWriter generator;
private final FetchPath fetchPath;
private final Map> visitors;
private final PathStack pathStack;
@@ -37,7 +37,7 @@ public final class WriteJson implements SpiJsonWriter {
/**
* Construct for full bean use (normal).
*/
- public WriteJson(SpiEbeanServer server, JsonGenerator generator, FetchPath fetchPath,
+ public WriteJson(SpiEbeanServer server, JsonWriter generator, FetchPath fetchPath,
Map> visitors, Object objectMapper, JsonConfig.Include include,
boolean includeLoadedImplicit) {
@@ -50,12 +50,14 @@ public final class WriteJson implements SpiJsonWriter {
this.includeLoadedImplicit = includeLoadedImplicit;
this.parentBeans = new ArrayStack<>();
this.pathStack = new PathStack();
+ this.generator.serializeNulls(isIncludeNull());
+ this.generator.serializeEmpty(isIncludeEmpty());
}
/**
* Construct for Json scalar use.
*/
- public WriteJson(JsonGenerator generator, JsonConfig.Include include) {
+ public WriteJson(JsonWriter generator, JsonConfig.Include include) {
this.generator = generator;
this.include = include;
this.includeLoadedImplicit = true;
@@ -65,6 +67,8 @@ public final class WriteJson implements SpiJsonWriter {
this.objectMapper = null;
this.parentBeans = null;
this.pathStack = null;
+ this.generator.serializeNulls(isIncludeNull());
+ this.generator.serializeEmpty(isIncludeEmpty());
}
/**
@@ -84,7 +88,7 @@ public final class WriteJson implements SpiJsonWriter {
}
@Override
- public JsonGenerator gen() {
+ public JsonWriter gen() {
return generator;
}
@@ -95,171 +99,113 @@ public final class WriteJson implements SpiJsonWriter {
@Override
public void writeStartObject(String key) {
- try {
- if (key != null) {
- generator.writeFieldName(key);
- }
- generator.writeStartObject();
- } catch (IOException e) {
- throw new JsonIOException(e);
+ if (key != null) {
+ generator.name(key);
}
+ generator.beginObject();
}
@Override
public void writeStartObject() {
- try {
- generator.writeStartObject();
- } catch (IOException e) {
- throw new JsonIOException(e);
- }
+ generator.beginObject();
}
@Override
public void writeEndObject() {
- try {
- generator.writeEndObject();
- } catch (IOException e) {
- throw new JsonIOException(e);
- }
+ generator.endObject();
}
@Override
public void writeStartArray(String key) {
- try {
- if (key != null) {
- generator.writeFieldName(key);
- }
- generator.writeStartArray();
- } catch (IOException e) {
- throw new JsonIOException(e);
+ if (key != null) {
+ generator.name(key);
}
+ generator.beginArray();
}
@Override
public void writeStartArray() {
- try {
- generator.writeStartArray();
- } catch (IOException e) {
- throw new JsonIOException(e);
- }
+ generator.beginArray();
}
@Override
public void writeEndArray() {
- try {
- generator.writeEndArray();
- } catch (IOException e) {
- throw new JsonIOException(e);
- }
+ generator.endArray();
}
@Override
public void writeRaw(String text) {
- try {
- generator.writeRaw(text);
- } catch (IOException e) {
- throw new JsonIOException(e);
- }
+ generator.rawChunkStart();
+ generator.rawChunk(text);
+ generator.rawChunkEnd();
}
@Override
public void writeRawValue(String text) {
- try {
- generator.writeRawValue(text);
- } catch (IOException e) {
- throw new JsonIOException(e);
- }
+ generator.rawValue(text);
}
@Override
public void writeFieldName(String name) {
- try {
- generator.writeFieldName(name);
- } catch (IOException e) {
- throw new JsonIOException(e);
- }
+ generator.name(name);
}
@Override
public void writeNullField(String name) {
if (isIncludeNull()) {
- try {
- generator.writeNullField(name);
- } catch (IOException e) {
- throw new JsonIOException(e);
- }
+ generator.name(name);
+ generator.nullValue();
}
}
@Override
public void writeNumberField(String name, long value) {
- try {
- generator.writeNumberField(name, value);
- } catch (IOException e) {
- throw new JsonIOException(e);
- }
+ generator.name(name);
+ generator.value(value);
}
@Override
public void writeNumberField(String name, double value) {
- try {
- generator.writeNumberField(name, value);
- } catch (IOException e) {
- throw new JsonIOException(e);
- }
+ generator.name(name);
+ generator.value(value);
}
@Override
public void writeNumberField(String name, int value) {
- try {
- generator.writeNumberField(name, value);
- } catch (IOException e) {
- throw new JsonIOException(e);
- }
+ generator.name(name);
+ generator.value(value);
}
@Override
public void writeNumberField(String name, short value) {
- try {
- generator.writeNumberField(name, value);
- } catch (IOException e) {
- throw new JsonIOException(e);
- }
+ generator.name(name);
+ generator.value(value);
}
@Override
public void writeNumberField(String name, float value) {
- try {
- generator.writeNumberField(name, value);
- } catch (IOException e) {
- throw new JsonIOException(e);
- }
+ generator.name(name);
+ generator.value((double) value);
}
@Override
public void writeNumberField(String name, BigDecimal value) {
- try {
- generator.writeNumberField(name, value);
- } catch (IOException e) {
- throw new JsonIOException(e);
- }
+ generator.name(name);
+ generator.value(value);
}
@Override
public void writeStringField(String name, String value) {
- try {
- generator.writeStringField(name, value);
- } catch (IOException e) {
- throw new JsonIOException(e);
- }
+ generator.name(name);
+ generator.value(value);
}
@Override
public void writeBinary(InputStream is, int length) {
try {
- generator.writeBinary(is, length);
+ generator.value(is.readNBytes(length));
} catch (IOException e) {
throw new JsonIOException(e);
}
@@ -267,83 +213,49 @@ public final class WriteJson implements SpiJsonWriter {
@Override
public void writeBinaryField(String name, byte[] value) {
- try {
- generator.writeBinaryField(name, value);
- } catch (IOException e) {
- throw new JsonIOException(e);
- }
+ generator.name(name);
+ generator.value(value);
}
@Override
public void writeBooleanField(String name, boolean value) {
- try {
- generator.writeBooleanField(name, value);
- } catch (IOException e) {
- throw new JsonIOException(e);
- }
+ generator.name(name);
+ generator.value(value);
}
@Override
public void writeBoolean(boolean value) {
- try {
- generator.writeBoolean(value);
- } catch (IOException e) {
- throw new JsonIOException(e);
- }
+ generator.value(value);
}
@Override
public void writeString(String value) {
- try {
- generator.writeString(value);
- } catch (IOException e) {
- throw new JsonIOException(e);
- }
+ generator.value(value);
}
@Override
public void writeNumber(int value) {
- try {
- generator.writeNumber(value);
- } catch (IOException e) {
- throw new JsonIOException(e);
- }
+ generator.value(value);
}
@Override
public void writeNumber(long value) {
- try {
- generator.writeNumber(value);
- } catch (IOException e) {
- throw new JsonIOException(e);
- }
+ generator.value(value);
}
@Override
public void writeNumber(double value) {
- try {
- generator.writeNumber(value);
- } catch (IOException e) {
- throw new JsonIOException(e);
- }
+ generator.value(value);
}
@Override
public void writeNumber(BigDecimal value) {
- try {
- generator.writeNumber(value);
- } catch (IOException e) {
- throw new JsonIOException(e);
- }
+ generator.value(value);
}
@Override
public void writeNull() {
- try {
- generator.writeNull();
- } catch (IOException e) {
- throw new JsonIOException(e);
- }
+ generator.nullValue();
}
@Override
@@ -375,55 +287,39 @@ public final class WriteJson implements SpiJsonWriter {
@Override
public void beginAssocMany(String key) {
- try {
- pathStack.pushPathKey(key);
- if (key != null) {
- generator.writeFieldName(key);
- }
- generator.writeStartArray();
- } catch (IOException e) {
- throw new JsonIOException(e);
+ pathStack.pushPathKey(key);
+ if (key != null) {
+ generator.name(key);
}
+ generator.beginArray();
}
@Override
public void endAssocMany() {
- try {
- pathStack.pop();
- generator.writeEndArray();
- } catch (IOException e) {
- throw new JsonIOException(e);
- }
+ pathStack.pop();
+ generator.endArray();
}
@Override
public void beginAssocManyMap(String key, boolean elementCollection) {
- try {
- pathStack.pushPathKey(key);
- if (key != null) {
- generator.writeFieldName(key);
- }
- if (elementCollection) {
- generator.writeStartObject();
- } else {
- generator.writeStartArray();
- }
- } catch (IOException e) {
- throw new JsonIOException(e);
+ pathStack.pushPathKey(key);
+ if (key != null) {
+ generator.name(key);
+ }
+ if (elementCollection) {
+ generator.beginObject();
+ } else {
+ generator.beginArray();
}
}
@Override
public void endAssocManyMap(boolean elementCollection) {
- try {
- pathStack.pop();
- if (elementCollection) {
- generator.writeEndObject();
- } else {
- generator.writeEndArray();
- }
- } catch (IOException e) {
- throw new JsonIOException(e);
+ pathStack.pop();
+ if (elementCollection) {
+ generator.endObject();
+ } else {
+ generator.endArray();
}
}
@@ -465,8 +361,8 @@ public final class WriteJson implements SpiJsonWriter {
}
}
try {
- generator.writeFieldName(name);
- objectMapper().writeValue(generator, value);
+ generator.name(name);
+ generator.rawValue(objectMapper().writeValueAsString(value));
} catch (IOException e) {
throw new JsonIOException(e);
}
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/readaudit/DefaultReadAuditLogger.java b/ebean-core/src/main/java/io/ebeaninternal/server/readaudit/DefaultReadAuditLogger.java
index 785dd57b5..167b2ce86 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/readaudit/DefaultReadAuditLogger.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/readaudit/DefaultReadAuditLogger.java
@@ -1,8 +1,8 @@
package io.ebeaninternal.server.readaudit;
-import com.fasterxml.jackson.core.JsonFactory;
-import com.fasterxml.jackson.core.JsonGenerator;
import io.avaje.applog.AppLog;
+import io.avaje.json.JsonWriter;
+import io.avaje.json.stream.JsonStream;
import io.ebean.event.readaudit.ReadAuditLogger;
import io.ebean.event.readaudit.ReadAuditQueryPlan;
import io.ebean.event.readaudit.ReadEvent;
@@ -24,7 +24,7 @@ public class DefaultReadAuditLogger implements ReadAuditLogger {
private static final System.Logger queryLogger = AppLog.getLogger("io.ebean.ReadAuditQuery");
private static final System.Logger auditLogger = AppLog.getLogger("io.ebean.ReadAudit");
- protected final JsonFactory jsonFactory = new JsonFactory();
+ protected final JsonStream jsonStream = JsonStream.builder().build();
protected final int defaultQueryBuffer = 500;
protected final int defaultReadBuffer = 150;
@@ -34,25 +34,26 @@ public class DefaultReadAuditLogger implements ReadAuditLogger {
@Override
public void queryPlan(ReadAuditQueryPlan queryPlan) {
StringWriter writer = new StringWriter(defaultQueryBuffer);
- try (JsonGenerator gen = jsonFactory.createGenerator(writer)) {
- gen.writeStartObject();
+ try (JsonWriter gen = jsonStream.writer(writer)) {
+ gen.beginObject();
String beanType = queryPlan.getBeanType();
if (beanType != null) {
- gen.writeStringField("beanType", beanType);
+ gen.name("beanType");
+ gen.value(beanType);
}
String queryKey = queryPlan.getQueryKey();
if (queryKey != null) {
- gen.writeStringField("queryKey", queryKey);
+ gen.name("queryKey");
+ gen.value(queryKey);
}
String sql = queryPlan.getSql();
if (sql != null) {
- gen.writeStringField("sql", sql);
+ gen.name("sql");
+ gen.value(sql);
}
- gen.writeEndObject();
+ gen.endObject();
gen.flush();
queryLogger.log(INFO, writer.toString());
- } catch (IOException e) {
- CoreLog.log.log(ERROR, "Error writing Read audit event", e);
}
}
@@ -73,56 +74,64 @@ public class DefaultReadAuditLogger implements ReadAuditLogger {
}
protected void writeEvent(ReadEvent event) {
- try {
- StringWriter writer = new StringWriter(defaultReadBuffer);
- JsonGenerator gen = jsonFactory.createGenerator(writer);
+ StringWriter writer = new StringWriter(defaultReadBuffer);
+ try (JsonWriter gen = jsonStream.writer(writer)) {
writeDetails(gen, event);
- auditLogger.log(INFO, writer.toString());
} catch (IOException e) {
CoreLog.log.log(ERROR, "Error writing Read audit event", e);
+ return;
}
+ auditLogger.log(INFO, writer.toString());
}
/**
* Write the details for the read bean or read many beans event.
*/
- protected void writeDetails(JsonGenerator gen, ReadEvent event) throws IOException {
- gen.writeStartObject();
+ protected void writeDetails(JsonWriter gen, ReadEvent event) throws IOException {
+ gen.beginObject();
String source = event.getSource();
if (source != null) {
- gen.writeStringField("source", source);
+ gen.name("source");
+ gen.value(source);
}
String userId = event.getUserId();
if (userId != null) {
- gen.writeStringField("userId", userId);
+ gen.name("userId");
+ gen.value(userId);
}
String userIpAddress = event.getUserIpAddress();
if (userIpAddress != null) {
- gen.writeStringField("userIpAddress", userIpAddress);
+ gen.name("userIpAddress");
+ gen.value(userIpAddress);
}
Map userContext = event.getUserContext();
if (userContext != null && !userContext.isEmpty()) {
- gen.writeObjectFieldStart("userContext");
+ gen.name("userContext");
+ gen.beginObject();
for (Map.Entry entry : userContext.entrySet()) {
- gen.writeStringField(entry.getKey(), entry.getValue());
+ gen.name(entry.getKey());
+ gen.value(entry.getValue());
}
- gen.writeEndObject();
+ gen.endObject();
}
- gen.writeNumberField("eventTime", event.getEventTime());
- gen.writeStringField("beanType", event.getBeanType());
- gen.writeStringField("queryKey", event.getQueryKey());
- gen.writeStringField("bindLog", event.getBindLog());
+ gen.name("eventTime");
+ gen.value(event.getEventTime());
+ gen.name("beanType");
+ gen.value(event.getBeanType());
+ gen.name("queryKey");
+ gen.value(event.getQueryKey());
+ gen.name("bindLog");
+ gen.value(event.getBindLog());
Object id = event.getId();
if (id != null) {
- gen.writeFieldName("id");
+ gen.name("id");
EJson.write(id, gen);
} else {
- gen.writeFieldName("ids");
+ gen.name("ids");
EJson.writeCollection(event.getIds(), gen);
}
- gen.writeEndObject();
+ gen.endObject();
gen.flush();
- gen.close();
}
}
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeArrayList.java b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeArrayList.java
index 59e85b54a..e976a5279 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeArrayList.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeArrayList.java
@@ -1,8 +1,8 @@
package io.ebeaninternal.server.type;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonParser;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonWriter;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.DocPropertyType;
import io.ebean.core.type.ScalarType;
@@ -173,12 +173,16 @@ class ScalarTypeArrayList extends ScalarTypeArrayBase implements ScalarTyp
}
@Override
- public List jsonRead(JsonParser parser) throws IOException {
- return convert(EJson.parseList(parser, parser.getCurrentToken()));
+ public List jsonRead(JsonReader parser) throws IOException {
+ if (parser.isNullValue()) {
+ return null;
+ }
+ List rawList = EJson.parseList(parser, parser.currentToken());
+ return convert(rawList);
}
@Override
- public void jsonWrite(JsonGenerator writer, List value) throws IOException {
+ public void jsonWrite(JsonWriter writer, List value) throws IOException {
EJson.write(value, writer);
}
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeArraySet.java b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeArraySet.java
index d1034be93..6ae1d817c 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeArraySet.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeArraySet.java
@@ -1,8 +1,8 @@
package io.ebeaninternal.server.type;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonParser;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonWriter;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.DocPropertyType;
import io.ebean.core.type.ScalarType;
@@ -152,12 +152,16 @@ class ScalarTypeArraySet extends ScalarTypeArrayBase implements ScalarTypeA
}
@Override
- public Set jsonRead(JsonParser parser) throws IOException {
- return convert(EJson.parseList(parser, parser.getCurrentToken()));
+ public Set jsonRead(JsonReader parser) throws IOException {
+ if (parser.isNullValue()) {
+ return null;
+ }
+ List rawList = EJson.parseList(parser, parser.currentToken());
+ return convert(rawList);
}
@Override
- public void jsonWrite(JsonGenerator writer, Set value) throws IOException {
+ public void jsonWrite(JsonWriter writer, Set value) throws IOException {
EJson.write(value, writer);
}
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeBigDecimal.java b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeBigDecimal.java
index c771ff59b..802e0051a 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeBigDecimal.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeBigDecimal.java
@@ -1,7 +1,7 @@
package io.ebeaninternal.server.type;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonParser;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonWriter;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.DataReader;
import io.ebean.core.type.DocPropertyType;
@@ -78,13 +78,13 @@ class ScalarTypeBigDecimal extends ScalarTypeBase {
}
@Override
- public BigDecimal jsonRead(JsonParser parser) throws IOException {
- return parser.getDecimalValue();
+ public BigDecimal jsonRead(JsonReader parser) throws IOException {
+ return parser.readDecimal();
}
@Override
- public void jsonWrite(JsonGenerator writer, BigDecimal value) throws IOException {
- writer.writeNumber(value);
+ public void jsonWrite(JsonWriter writer, BigDecimal value) throws IOException {
+ writer.value(value);
}
@Override
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeBoolean.java b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeBoolean.java
index 62aa6c553..690a46b90 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeBoolean.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeBoolean.java
@@ -1,8 +1,7 @@
package io.ebeaninternal.server.type;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonToken;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonWriter;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.DataReader;
import io.ebean.core.type.DocPropertyType;
@@ -348,13 +347,39 @@ public final class ScalarTypeBoolean {
}
@Override
- public Boolean jsonRead(JsonParser parser) {
- return JsonToken.VALUE_TRUE == parser.getCurrentToken() ? Boolean.TRUE : Boolean.FALSE;
+ public Boolean jsonRead(JsonReader parser) {
+ if (parser.isNullValue()) {
+ return null;
+ }
+ var token = parser.currentToken();
+ if (token == JsonReader.Token.BOOLEAN) {
+ return parser.readBoolean();
+ }
+ if (token == JsonReader.Token.NUMBER) {
+ return parser.readDecimal().intValue() == 1;
+ }
+ if (token == JsonReader.Token.STRING) {
+ return parse(parser.readString());
+ }
+ String raw = parser.readRaw();
+ if (raw == null || "null".equals(raw)) {
+ return null;
+ }
+ if ("true".equals(raw) || "1".equals(raw)) {
+ return Boolean.TRUE;
+ }
+ if ("false".equals(raw) || "0".equals(raw)) {
+ return Boolean.FALSE;
+ }
+ if (raw.length() > 1 && raw.charAt(0) == '"' && raw.charAt(raw.length() - 1) == '"') {
+ return parse(raw.substring(1, raw.length() - 1));
+ }
+ return parse(raw);
}
@Override
- public void jsonWrite(JsonGenerator writer, Boolean value) throws IOException {
- writer.writeBoolean(value);
+ public void jsonWrite(JsonWriter writer, Boolean value) throws IOException {
+ writer.value(value);
}
@Override
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeByte.java b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeByte.java
index e01bc625e..c087e4720 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeByte.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeByte.java
@@ -1,7 +1,7 @@
package io.ebeaninternal.server.type;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonParser;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonWriter;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.DataReader;
import io.ebean.core.type.DocPropertyType;
@@ -9,7 +9,6 @@ import io.ebean.core.type.ScalarTypeBase;
import io.ebean.text.TextException;
import io.ebean.core.type.BasicTypeConverter;
-import java.io.ByteArrayOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
@@ -55,15 +54,13 @@ final class ScalarTypeByte extends ScalarTypeBase {
}
@Override
- public void jsonWrite(JsonGenerator writer, Byte value) throws IOException {
- writer.writeBinary(new byte[]{value});
+ public void jsonWrite(JsonWriter writer, Byte value) throws IOException {
+ writer.value(new byte[]{value});
}
@Override
- public Byte jsonRead(JsonParser parser) throws IOException {
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- parser.readBinaryValue(os);
- byte[] bytes = os.toByteArray();
+ public Byte jsonRead(JsonReader parser) throws IOException {
+ byte[] bytes = parser.readBinary();
if (bytes.length == 0) {
return null;
} else {
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeBytesBase.java b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeBytesBase.java
index a5647e8a7..1165c5c52 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeBytesBase.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeBytesBase.java
@@ -1,13 +1,12 @@
package io.ebeaninternal.server.type;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonParser;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonWriter;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.DocPropertyType;
import io.ebean.core.type.ScalarTypeBase;
import io.ebean.text.TextException;
-import java.io.ByteArrayOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
@@ -85,15 +84,13 @@ public abstract class ScalarTypeBytesBase extends ScalarTypeBase {
}
@Override
- public void jsonWrite(JsonGenerator writer, byte[] value) throws IOException {
- writer.writeBinary(value);
+ public void jsonWrite(JsonWriter writer, byte[] value) throws IOException {
+ writer.value(value);
}
@Override
- public byte[] jsonRead(JsonParser parser) throws IOException {
- ByteArrayOutputStream out = new ByteArrayOutputStream(500);
- parser.readBinaryValue(out);
- return out.toByteArray();
+ public byte[] jsonRead(JsonReader parser) throws IOException {
+ return parser.readBinary();
}
@Override
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeBytesEncrypted.java b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeBytesEncrypted.java
index 3fdc0f5b2..416fa17f0 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeBytesEncrypted.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeBytesEncrypted.java
@@ -1,13 +1,12 @@
package io.ebeaninternal.server.type;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonParser;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonWriter;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.DataReader;
import io.ebean.core.type.DocPropertyType;
import io.ebean.core.type.ScalarType;
-import java.io.ByteArrayOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
@@ -58,15 +57,13 @@ public final class ScalarTypeBytesEncrypted implements ScalarType {
}
@Override
- public void jsonWrite(JsonGenerator writer, byte[] value) throws IOException {
- writer.writeBinary(value);
+ public void jsonWrite(JsonWriter writer, byte[] value) throws IOException {
+ writer.value(value);
}
@Override
- public byte[] jsonRead(JsonParser parser) throws IOException {
- ByteArrayOutputStream out = new ByteArrayOutputStream(500);
- parser.readBinaryValue(out);
- return out.toByteArray();
+ public byte[] jsonRead(JsonReader parser) throws IOException {
+ return parser.readBinary();
}
@Override
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeCharArray.java b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeCharArray.java
index ff74e0cfe..2f50d3696 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeCharArray.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeCharArray.java
@@ -1,6 +1,6 @@
package io.ebeaninternal.server.type;
-import com.fasterxml.jackson.core.JsonParser;
+import io.avaje.json.JsonReader;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.DataReader;
import io.ebean.core.type.ScalarTypeBaseVarchar;
@@ -72,7 +72,7 @@ final class ScalarTypeCharArray extends ScalarTypeBaseVarchar {
}
@Override
- public char[] jsonRead(JsonParser parser) throws IOException {
- return parser.getValueAsString().toCharArray();
+ public char[] jsonRead(JsonReader parser) throws IOException {
+ return parser.readString().toCharArray();
}
}
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeDouble.java b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeDouble.java
index 3fe5deba0..6b21c1a1c 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeDouble.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeDouble.java
@@ -1,7 +1,7 @@
package io.ebeaninternal.server.type;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonParser;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonWriter;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.DataReader;
import io.ebean.core.type.DocPropertyType;
@@ -77,13 +77,13 @@ final class ScalarTypeDouble extends ScalarTypeBase {
}
@Override
- public Double jsonRead(JsonParser parser) throws IOException {
- return parser.getDoubleValue();
+ public Double jsonRead(JsonReader parser) throws IOException {
+ return parser.readDouble();
}
@Override
- public void jsonWrite(JsonGenerator writer, Double value) throws IOException {
- writer.writeNumber(value);
+ public void jsonWrite(JsonWriter writer, Double value) throws IOException {
+ writer.value(value);
}
@Override
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeDuration.java b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeDuration.java
index 1589a22af..a75f53bac 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeDuration.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeDuration.java
@@ -1,7 +1,7 @@
package io.ebeaninternal.server.type;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonParser;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonWriter;
import io.ebean.core.type.*;
import java.io.DataInput;
@@ -90,13 +90,13 @@ class ScalarTypeDuration extends ScalarTypeBase {
}
@Override
- public Duration jsonRead(JsonParser parser) throws IOException {
- return Duration.parse(parser.getValueAsString());
+ public Duration jsonRead(JsonReader parser) throws IOException {
+ return Duration.parse(parser.readString());
}
@Override
- public void jsonWrite(JsonGenerator writer, Duration value) throws IOException {
- writer.writeString(value.toString());
+ public void jsonWrite(JsonWriter writer, Duration value) throws IOException {
+ writer.value(value.toString());
}
@Override
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeEncryptedWrapper.java b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeEncryptedWrapper.java
index 627d32a65..4d37a007d 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeEncryptedWrapper.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeEncryptedWrapper.java
@@ -1,7 +1,7 @@
package io.ebeaninternal.server.type;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonParser;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonWriter;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.DataReader;
import io.ebean.core.type.DocPropertyType;
@@ -120,12 +120,12 @@ public final class ScalarTypeEncryptedWrapper implements ScalarType, Local
}
@Override
- public T jsonRead(JsonParser parser) throws IOException {
+ public T jsonRead(JsonReader parser) throws IOException {
return wrapped.jsonRead(parser);
}
@Override
- public void jsonWrite(JsonGenerator writer, T value) throws IOException {
+ public void jsonWrite(JsonWriter writer, T value) throws IOException {
wrapped.jsonWrite(writer, value);
}
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeEnumStandard.java b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeEnumStandard.java
index 227520fbf..2a0476921 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeEnumStandard.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeEnumStandard.java
@@ -1,11 +1,11 @@
package io.ebeaninternal.server.type;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonParser;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.DataReader;
import io.ebean.core.type.DocPropertyType;
import io.ebean.core.type.ScalarTypeBase;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonWriter;
import jakarta.persistence.EnumType;
import java.io.DataInput;
@@ -228,20 +228,19 @@ final class ScalarTypeEnumStandard {
}
@Override
- public Object jsonRead(JsonParser parser) throws IOException {
- if (parser.getCodec() != null) {
- return parser.readValueAs(enumType);
- } else {
- return parse(parser.getValueAsString());
+ public Object jsonRead(JsonReader parser) throws IOException {
+ if (parser.isNullValue()) {
+ return null;
}
+ return parse(parser.readString());
}
@Override
- public void jsonWrite(JsonGenerator writer, Object value) throws IOException {
- if (writer.getCodec() != null) {
- writer.writeObject(value);
+ public void jsonWrite(JsonWriter writer, Object value) throws IOException {
+ if (value == null) {
+ writer.nullValue();
} else {
- writer.writeString(formatValue(value));
+ writer.value(formatValue(value));
}
}
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeFile.java b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeFile.java
index 5e4ad5df8..01ab9747d 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeFile.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeFile.java
@@ -1,7 +1,7 @@
package io.ebeaninternal.server.type;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonParser;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonWriter;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.DataReader;
import io.ebean.core.type.DocPropertyType;
@@ -102,16 +102,17 @@ final class ScalarTypeFile extends ScalarTypeBase {
}
@Override
- public void jsonWrite(JsonGenerator writer, File value) throws IOException {
- InputStream is = getInputStream(value);
- writer.writeBinary(is, (int) value.length());
+ public void jsonWrite(JsonWriter writer, File value) throws IOException {
+ try (InputStream is = getInputStream(value)) {
+ writer.value(is.readAllBytes());
+ }
}
@Override
- public File jsonRead(JsonParser parser) throws IOException {
+ public File jsonRead(JsonReader parser) throws IOException {
File tempFile = File.createTempFile(prefix, suffix, directory);
try (OutputStream os = getOutputStream(tempFile)) {
- parser.readBinaryValue(os);
+ os.write(parser.readBinary());
os.flush();
}
return tempFile;
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeFloat.java b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeFloat.java
index facea6618..6e2f1acdc 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeFloat.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeFloat.java
@@ -1,7 +1,7 @@
package io.ebeaninternal.server.type;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonParser;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonWriter;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.DataReader;
import io.ebean.core.type.DocPropertyType;
@@ -77,13 +77,13 @@ final class ScalarTypeFloat extends ScalarTypeBase {
}
@Override
- public Float jsonRead(JsonParser parser) throws IOException {
- return parser.getFloatValue();
+ public Float jsonRead(JsonReader parser) throws IOException {
+ return (float) parser.readDouble();
}
@Override
- public void jsonWrite(JsonGenerator writer, Float value) throws IOException {
- writer.writeNumber(value);
+ public void jsonWrite(JsonWriter writer, Float value) throws IOException {
+ writer.value(value.doubleValue());
}
@Override
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeInteger.java b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeInteger.java
index aea3b8d16..97ea05207 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeInteger.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeInteger.java
@@ -1,7 +1,7 @@
package io.ebeaninternal.server.type;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonParser;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonWriter;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.DataReader;
import io.ebean.core.type.DocPropertyType;
@@ -87,13 +87,13 @@ final class ScalarTypeInteger extends ScalarTypeBase {
}
@Override
- public Integer jsonRead(JsonParser parser) throws IOException {
- return parser.getIntValue();
+ public Integer jsonRead(JsonReader parser) throws IOException {
+ return parser.readInt();
}
@Override
- public void jsonWrite(JsonGenerator writer, Integer value) throws IOException {
- writer.writeNumber(value);
+ public void jsonWrite(JsonWriter writer, Integer value) throws IOException {
+ writer.value(value);
}
@Override
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeJsonList.java b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeJsonList.java
index 8d43c7d38..51da2bbc2 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeJsonList.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeJsonList.java
@@ -1,7 +1,7 @@
package io.ebeaninternal.server.type;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonParser;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonWriter;
import io.ebean.config.dbplatform.DbPlatformType;
import io.ebean.core.type.*;
import io.ebean.text.TextException;
@@ -182,12 +182,12 @@ final class ScalarTypeJsonList {
}
@Override
- public final List jsonRead(JsonParser parser) throws IOException {
- return EJson.parseList(parser, parser.getCurrentToken());
+ public final List jsonRead(JsonReader parser) throws IOException {
+ return EJson.parseList(parser, parser.currentToken());
}
@Override
- public final void jsonWrite(JsonGenerator writer, List value) throws IOException {
+ public final void jsonWrite(JsonWriter writer, List value) throws IOException {
EJson.write(value, writer);
}
}
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeJsonMap.java b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeJsonMap.java
index a97b9911c..5bc0a4bef 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeJsonMap.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeJsonMap.java
@@ -1,7 +1,7 @@
package io.ebeaninternal.server.type;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonParser;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonWriter;
import io.ebean.config.dbplatform.DbPlatformType;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.DataReader;
@@ -235,13 +235,13 @@ abstract class ScalarTypeJsonMap extends ScalarTypeBase
+
+ io.avaje
+ avaje-json-core
+ ${avaje-json-core.version}
+ provided
+
+
com.fasterxml.jackson.corejackson-core
diff --git a/ebean-jackson-mapper/src/main/java/io/ebean/jackson/mapper/ScalarJsonJacksonMapper.java b/ebean-jackson-mapper/src/main/java/io/ebean/jackson/mapper/ScalarJsonJacksonMapper.java
index dad6d8bca..31af96e49 100644
--- a/ebean-jackson-mapper/src/main/java/io/ebean/jackson/mapper/ScalarJsonJacksonMapper.java
+++ b/ebean-jackson-mapper/src/main/java/io/ebean/jackson/mapper/ScalarJsonJacksonMapper.java
@@ -1,13 +1,13 @@
package io.ebean.jackson.mapper;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.introspect.AnnotatedClass;
import com.fasterxml.jackson.databind.introspect.AnnotatedField;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonWriter;
import io.ebean.annotation.MutationDetection;
import io.ebean.core.type.*;
import io.ebean.text.TextException;
@@ -221,13 +221,20 @@ public final class ScalarJsonJacksonMapper implements ScalarJsonMapper {
}
@Override
- public final T jsonRead(JsonParser parser) throws IOException {
- return objectReader.readValue(parser, deserType);
+ public final T jsonRead(JsonReader parser) throws IOException {
+ if (parser.isNullValue()) {
+ return null;
+ }
+ return objectReader.readValue(parser.readRaw(), deserType);
}
@Override
- public final void jsonWrite(JsonGenerator writer, T value) throws IOException {
- objectWriter.writeValue(writer, value);
+ public final void jsonWrite(JsonWriter writer, T value) throws IOException {
+ if (value == null) {
+ writer.nullValue();
+ } else {
+ writer.rawValue(objectWriter.writeValueAsString(value));
+ }
}
@Override
diff --git a/ebean-jackson-mapper/src/main/java/module-info.java b/ebean-jackson-mapper/src/main/java/module-info.java
index 7adf6352a..7e4d4b239 100644
--- a/ebean-jackson-mapper/src/main/java/module-info.java
+++ b/ebean-jackson-mapper/src/main/java/module-info.java
@@ -2,6 +2,7 @@ import io.ebean.jackson.mapper.ScalarJsonJacksonMapper;
module io.ebean.jackson.mapper {
+ requires io.avaje.json;
requires io.ebean.core.type;
requires com.fasterxml.jackson.annotation;
requires com.fasterxml.jackson.core;
diff --git a/ebean-net-postgis-types/src/main/java/io/ebean/postgis/ScalarTypePgisBase.java b/ebean-net-postgis-types/src/main/java/io/ebean/postgis/ScalarTypePgisBase.java
index 8ed62a387..68b24773b 100644
--- a/ebean-net-postgis-types/src/main/java/io/ebean/postgis/ScalarTypePgisBase.java
+++ b/ebean-net-postgis-types/src/main/java/io/ebean/postgis/ScalarTypePgisBase.java
@@ -1,7 +1,7 @@
package io.ebean.postgis;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonParser;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonWriter;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.DataReader;
import io.ebean.core.type.DocPropertyType;
@@ -107,12 +107,12 @@ abstract class ScalarTypePgisBase implements ScalarType {
}
@Override
- public T jsonRead(JsonParser parser) {
+ public T jsonRead(JsonReader parser) {
return null;
}
@Override
- public void jsonWrite(JsonGenerator writer, T value) {
+ public void jsonWrite(JsonWriter writer, T value) {
}
}
diff --git a/ebean-pgvector-types/src/main/java/io/ebean/pgvector/ScalarTypePGbase.java b/ebean-pgvector-types/src/main/java/io/ebean/pgvector/ScalarTypePGbase.java
index 4bb7baa34..ec4e2d60a 100644
--- a/ebean-pgvector-types/src/main/java/io/ebean/pgvector/ScalarTypePGbase.java
+++ b/ebean-pgvector-types/src/main/java/io/ebean/pgvector/ScalarTypePGbase.java
@@ -1,7 +1,7 @@
package io.ebean.pgvector;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonParser;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonWriter;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.DataReader;
import io.ebean.core.type.DocPropertyType;
@@ -85,12 +85,12 @@ abstract class ScalarTypePGbase implements ScalarType {
}
@Override
- public T jsonRead(JsonParser parser) {
+ public T jsonRead(JsonReader parser) {
return null;
}
@Override
- public void jsonWrite(JsonGenerator writer, T value) {
+ public void jsonWrite(JsonWriter writer, T value) {
}
}
diff --git a/ebean-postgis-types/src/main/java/io/ebean/postgis/ScalarTypePgisBase.java b/ebean-postgis-types/src/main/java/io/ebean/postgis/ScalarTypePgisBase.java
index 243b8cba7..6669cdb18 100644
--- a/ebean-postgis-types/src/main/java/io/ebean/postgis/ScalarTypePgisBase.java
+++ b/ebean-postgis-types/src/main/java/io/ebean/postgis/ScalarTypePgisBase.java
@@ -1,7 +1,7 @@
package io.ebean.postgis;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonParser;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonWriter;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.DataReader;
import io.ebean.core.type.DocPropertyType;
@@ -107,12 +107,12 @@ abstract class ScalarTypePgisBase implements ScalarType {
}
@Override
- public T jsonRead(JsonParser parser) {
+ public T jsonRead(JsonReader parser) {
return null;
}
@Override
- public void jsonWrite(JsonGenerator writer, T value) {
+ public void jsonWrite(JsonWriter writer, T value) {
}
}
diff --git a/ebean-postgis-types/src/main/java/io/ebean/postgis/latte/ScalarTypeGeoLatteBase.java b/ebean-postgis-types/src/main/java/io/ebean/postgis/latte/ScalarTypeGeoLatteBase.java
index cd6a74054..df84f4ae6 100644
--- a/ebean-postgis-types/src/main/java/io/ebean/postgis/latte/ScalarTypeGeoLatteBase.java
+++ b/ebean-postgis-types/src/main/java/io/ebean/postgis/latte/ScalarTypeGeoLatteBase.java
@@ -1,7 +1,7 @@
package io.ebean.postgis.latte;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonParser;
+import io.avaje.json.JsonReader;
+import io.avaje.json.JsonWriter;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.DataReader;
import io.ebean.core.type.DocPropertyType;
@@ -103,12 +103,12 @@ abstract class ScalarTypeGeoLatteBase implements ScalarType<
}
@Override
- public T jsonRead(JsonParser parser) {
+ public T jsonRead(JsonReader parser) {
return null;
}
@Override
- public void jsonWrite(JsonGenerator writer, T value) {
+ public void jsonWrite(JsonWriter writer, T value) {
}
}
diff --git a/ebean-test/src/main/java/io/ebean/test/DbJson.java b/ebean-test/src/main/java/io/ebean/test/DbJson.java
index 3675063c1..09597b297 100644
--- a/ebean-test/src/main/java/io/ebean/test/DbJson.java
+++ b/ebean-test/src/main/java/io/ebean/test/DbJson.java
@@ -102,8 +102,8 @@ public class DbJson {
public PrettyJson replace(String... propertyNames) {
for (String propertyName : propertyNames) {
String placeholder = "\"" + propertyName + "\": " + placeHolder;
- rawJson = rawJson.replaceAll("\"" + propertyName + "\": (\\d+)", placeholder);
- rawJson = rawJson.replaceAll("\"" + propertyName + "\": \"(.*?)\"", placeholder);
+ rawJson = rawJson.replaceAll("\"" + propertyName + "\":\\s*(\\d+)", placeholder);
+ rawJson = rawJson.replaceAll("\"" + propertyName + "\":\\s*\"(.*?)\"", placeholder);
}
return this;
}
@@ -134,7 +134,9 @@ public class DbJson {
* Normalise line ending characters to just use new line.
*/
private String lineEnd(String content) {
- return content.replace("\r\n", "\n");
+ return content
+ .replace("\r\n", "\n")
+ .replaceAll("\"([^\"]+)\":\\s+", "\"$1\": ");
}
/**
diff --git a/ebean-test/src/test/java/io/ebean/xtest/internal/server/text/json/DJsonScalarTest.java b/ebean-test/src/test/java/io/ebean/xtest/internal/server/text/json/DJsonScalarTest.java
index e39ee30db..e90f37f77 100644
--- a/ebean-test/src/test/java/io/ebean/xtest/internal/server/text/json/DJsonScalarTest.java
+++ b/ebean-test/src/test/java/io/ebean/xtest/internal/server/text/json/DJsonScalarTest.java
@@ -1,7 +1,7 @@
package io.ebean.xtest.internal.server.text.json;
-import com.fasterxml.jackson.core.JsonFactory;
-import com.fasterxml.jackson.core.JsonGenerator;
+import io.avaje.json.JsonWriter;
+import io.avaje.json.stream.JsonStream;
import io.ebean.DatabaseBuilder;
import io.ebean.config.DatabaseConfig;
import io.ebean.platform.h2.H2Platform;
@@ -22,6 +22,7 @@ import static org.assertj.core.api.Assertions.assertThat;
public class DJsonScalarTest {
private final DJsonScalar jsonScalar;
+ private final JsonStream jsonStream = JsonStream.builder().build();
public DJsonScalarTest() {
var serverConfig = new DatabaseConfig();
@@ -33,37 +34,35 @@ public class DJsonScalarTest {
@Test
public void writeBasicTypes() throws IOException {
StringWriter writer = new StringWriter();
- JsonGenerator generator = createGenerator(writer);
+ JsonWriter generator = createGenerator(writer);
UUID uuid = UUID.randomUUID();
LocalDate today = LocalDate.now();
- generator.writeRaw("[");
+ generator.rawChunk('[');
jsonScalar.write(generator, "hello");
- generator.writeRaw(",");
+ generator.rawChunk(',');
jsonScalar.write(generator, uuid);
- generator.writeRaw(",");
+ generator.rawChunk(',');
jsonScalar.write(generator, today);
- generator.writeRaw("]");
+ generator.rawChunk(']');
generator.flush();
- generator.close();
String json = writer.toString();
assertThat(json).contains("hello");
assertThat(json).contains(uuid.toString());
}
- private JsonGenerator createGenerator(StringWriter writer) throws IOException {
- JsonFactory factory = new JsonFactory();
- return factory.createGenerator(writer);
+ private JsonWriter createGenerator(StringWriter writer) {
+ return jsonStream.writer(writer);
}
@Test
public void writeDbArrayTypes() throws IOException {
StringWriter writer = new StringWriter();
- JsonGenerator generator = createGenerator(writer);
+ JsonWriter generator = createGenerator(writer);
List list = new ArrayList<>();
list.add(UUID.randomUUID());
@@ -72,10 +71,9 @@ public class DJsonScalarTest {
jsonScalar.write(generator, list);
generator.flush();
- generator.close();
String json = writer.toString();
- assertThat(json).isEqualTo("[\""+list.get(0)+"\", \""+list.get(1)+"\"]");
+ assertThat(json).isEqualTo("[\"" + list.get(0) + "\",\"" + list.get(1) + "\"]");
}
}
diff --git a/ebean-test/src/test/java/io/ebean/xtest/internal/server/text/json/WriteJsonDirtyTest.java b/ebean-test/src/test/java/io/ebean/xtest/internal/server/text/json/WriteJsonDirtyTest.java
index f18a5cb82..0833fb439 100644
--- a/ebean-test/src/test/java/io/ebean/xtest/internal/server/text/json/WriteJsonDirtyTest.java
+++ b/ebean-test/src/test/java/io/ebean/xtest/internal/server/text/json/WriteJsonDirtyTest.java
@@ -1,7 +1,7 @@
package io.ebean.xtest.internal.server.text.json;
-import com.fasterxml.jackson.core.JsonFactory;
-import com.fasterxml.jackson.core.JsonGenerator;
+import io.avaje.json.JsonWriter;
+import io.avaje.json.stream.JsonStream;
import io.ebean.DB;
import io.ebean.bean.EntityBean;
import io.ebeaninternal.api.SpiEbeanServer;
@@ -20,6 +20,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
public class WriteJsonDirtyTest {
+ private static final JsonStream JSON_STREAM = JsonStream.builder().build();
+
@Test
public void test() throws IOException {
@@ -40,14 +42,12 @@ public class WriteJsonDirtyTest {
boolean[] dirtyProperties = entityBean._ebean_getIntercept().dirtyProperties();
StringWriter writer = new StringWriter();
- JsonFactory jsonFactory = new JsonFactory();
- JsonGenerator generator = jsonFactory.createGenerator(writer);
+ JsonWriter generator = JSON_STREAM.writer(writer);
WriteJson writeJson = new WriteJson(server, generator, null, null, null, null, true);
descriptor.jsonWriteDirty(writeJson, entityBean, dirtyProperties);
generator.flush();
- generator.close();
String jsonContent = writer.toString();
assertTrue(jsonContent.contains("\"name\":"));
diff --git a/ebean-test/src/test/java/io/ebean/xtest/internal/server/text/json/WriteJsonTest.java b/ebean-test/src/test/java/io/ebean/xtest/internal/server/text/json/WriteJsonTest.java
index ce0625827..629d79eab 100644
--- a/ebean-test/src/test/java/io/ebean/xtest/internal/server/text/json/WriteJsonTest.java
+++ b/ebean-test/src/test/java/io/ebean/xtest/internal/server/text/json/WriteJsonTest.java
@@ -28,8 +28,8 @@ class WriteJsonTest {
String json = DB.json().toJsonPretty(list);
- assertThat(json).contains("\"customer\": {");
- assertThat(json).contains("\"billingAddress\": {");
- assertThat(json).contains("\"details\": [ {");
+ assertThat(json).contains("\"customer\":");
+ assertThat(json).contains("\"billingAddress\":");
+ assertThat(json).contains("\"details\": [");
}
}
diff --git a/ebean-test/src/test/java/io/ebean/xtest/json/EJsonTests.java b/ebean-test/src/test/java/io/ebean/xtest/json/EJsonTests.java
index 7e721333f..c31e61bc0 100644
--- a/ebean-test/src/test/java/io/ebean/xtest/json/EJsonTests.java
+++ b/ebean-test/src/test/java/io/ebean/xtest/json/EJsonTests.java
@@ -1,7 +1,7 @@
package io.ebean.xtest.json;
-import com.fasterxml.jackson.core.JsonFactory;
-import com.fasterxml.jackson.core.JsonParser;
+import io.avaje.json.JsonReader;
+import io.avaje.json.stream.JsonStream;
import io.ebean.ModifyAwareType;
import io.ebean.text.json.EJson;
import io.ebean.util.IOUtils;
@@ -20,14 +20,13 @@ import static org.junit.jupiter.api.Assertions.*;
public class EJsonTests {
+ private static final JsonStream JSON_STREAM = JsonStream.builder().build();
+
@Test
public void test_map_simple() throws IOException {
- JsonFactory factory = new JsonFactory();
-
String jsonInput = "{\"name\":\"rob\",\"age\":12}";
-
- JsonParser jsonParser = factory.createParser(jsonInput);
+ JsonReader jsonParser = JSON_STREAM.reader(jsonInput);
Object result = EJson.parse(jsonParser);
@@ -56,11 +55,8 @@ public class EJsonTests {
@Test
public void test_parseObject() throws IOException {
- JsonFactory factory = new JsonFactory();
-
String jsonInput = "{\"name\":\"rob\",\"age\":12}";
-
- JsonParser jsonParser = factory.createParser(jsonInput);
+ JsonReader jsonParser = JSON_STREAM.reader(jsonInput);
Map map = EJson.parseObject(jsonParser);
@@ -168,8 +164,7 @@ public class EJsonTests {
String jsonInput = "[\"name\",\"rob\",12,13]";
- JsonFactory jsonFactory = new JsonFactory();
- JsonParser parser = jsonFactory.createParser(jsonInput);
+ JsonReader parser = JSON_STREAM.reader(jsonInput);
List list = EJson.parseList(parser);
diff --git a/ebean-test/src/test/java/io/ebean/xtest/json/JsonBeanReaderTest.java b/ebean-test/src/test/java/io/ebean/xtest/json/JsonBeanReaderTest.java
index 9c4cfdc0c..01b713bca 100644
--- a/ebean-test/src/test/java/io/ebean/xtest/json/JsonBeanReaderTest.java
+++ b/ebean-test/src/test/java/io/ebean/xtest/json/JsonBeanReaderTest.java
@@ -1,6 +1,6 @@
package io.ebean.xtest.json;
-import com.fasterxml.jackson.core.JsonParser;
+import io.avaje.json.JsonReader;
import io.ebean.xtest.BaseTestCase;
import io.ebean.DB;
import io.ebean.bean.PersistenceContext;
@@ -22,7 +22,7 @@ public class JsonBeanReaderTest extends BaseTestCase {
@Test
public void read() {
- JsonParser parser = getParser();
+ JsonReader parser = getParser();
JsonBeanReader beanReader = json.createBeanReader(Customer.class, parser, null);
Customer customer = beanReader.read();
@@ -30,7 +30,7 @@ public class JsonBeanReaderTest extends BaseTestCase {
assertThat(customer.getName()).isEqualTo("dummy");
}
- private JsonParser getParser() {
+ private JsonReader getParser() {
Customer customer = new Customer();
customer.setId(42);
@@ -45,11 +45,11 @@ public class JsonBeanReaderTest extends BaseTestCase {
@Test
public void forJson() {
- JsonParser parser = getParser();
+ JsonReader parser = getParser();
JsonBeanReader beanReader = json.createBeanReader(Customer.class, parser, null);
beanReader.read();
- JsonParser more = getParser();
+ JsonReader more = getParser();
JsonBeanReader moreReader = beanReader.forJson(more);
Customer customer = moreReader.read();
@@ -60,7 +60,7 @@ public class JsonBeanReaderTest extends BaseTestCase {
@Test
public void persistenceContextPut_when_noPC() throws Exception {
- JsonParser parser = getParser();
+ JsonReader parser = getParser();
JsonBeanReader beanReader = json.createBeanReader(Customer.class, parser, null);
beanReader.read();
@@ -75,7 +75,7 @@ public class JsonBeanReaderTest extends BaseTestCase {
JsonReadOptions options = new JsonReadOptions().setEnableLazyLoading(true);
- JsonParser parser = getParser();
+ JsonReader parser = getParser();
JsonBeanReader beanReader = json.createBeanReader(Customer.class, parser, options);
Customer customer = beanReader.read();
diff --git a/ebean-test/src/test/java/io/ebean/xtest/json/JsonContextTest.java b/ebean-test/src/test/java/io/ebean/xtest/json/JsonContextTest.java
index ba9606b16..c2c507831 100644
--- a/ebean-test/src/test/java/io/ebean/xtest/json/JsonContextTest.java
+++ b/ebean-test/src/test/java/io/ebean/xtest/json/JsonContextTest.java
@@ -1,6 +1,6 @@
package io.ebean.xtest.json;
-import com.fasterxml.jackson.core.JsonGenerator;
+import io.avaje.json.JsonWriter;
import io.ebean.DB;
import io.ebean.text.PathProperties;
import io.ebean.text.json.JsonContext;
@@ -90,8 +90,8 @@ public class JsonContextTest {
.findList();
String json = DB.json().toJsonPretty(orders);
- assertThat(json).contains("[ {");
- assertThat(json).contains("\"customer\": {");
+ assertThat(json).contains("[");
+ assertThat(json).contains("\"customer\":");
}
@Test
@@ -185,7 +185,7 @@ public class JsonContextTest {
StringWriter writer = new StringWriter();
JsonContext json = DB.json();
- JsonGenerator generator = json.createGenerator(writer);
+ JsonWriter generator = json.createGenerator(writer);
Customer customer = new Customer();
customer.setId(1);
@@ -194,10 +194,10 @@ public class JsonContextTest {
// we can use the generator before and after our json.toJson() call
// ... confirming we are not closing the generator
- generator.writeStartArray();
+ generator.beginArray();
json.toJson(customer, generator, PathProperties.parse("id,name"));
- generator.writeEndArray();
- generator.close();
+ generator.endArray();
+ generator.flush();
String jsonString = writer.toString();
assertThat(jsonString).startsWith("[");
@@ -210,17 +210,18 @@ public class JsonContextTest {
StringWriter writer = new StringWriter();
JsonContext json = DB.json();
- JsonGenerator generator = json.createGenerator(writer);
+ JsonWriter generator = json.createGenerator(writer);
// test that we can write anything via writeRaw()
- generator.writeRaw("START");
- generator.writeStartArray();
- generator.writeStartObject();
- generator.writeNumberField("count", 12);
- generator.writeEndObject();
- generator.writeEndArray();
- generator.writeRaw("END");
- generator.close();
+ generator.rawChunk("START");
+ generator.beginArray();
+ generator.beginObject();
+ generator.name("count");
+ generator.value(12);
+ generator.endObject();
+ generator.endArray();
+ generator.rawChunk("END");
+ generator.flush();
assertEquals("START[{\"count\":12}]END", writer.toString());
}
diff --git a/ebean-test/src/test/java/org/tests/text/json/TestJsonBeanDescriptorParse.java b/ebean-test/src/test/java/org/tests/text/json/TestJsonBeanDescriptorParse.java
index 96465c4d3..a26eecdf7 100644
--- a/ebean-test/src/test/java/org/tests/text/json/TestJsonBeanDescriptorParse.java
+++ b/ebean-test/src/test/java/org/tests/text/json/TestJsonBeanDescriptorParse.java
@@ -1,6 +1,7 @@
package org.tests.text.json;
-import com.fasterxml.jackson.core.JsonParser;
+import io.avaje.json.JsonReader;
+import io.avaje.json.stream.JsonStream;
import io.ebean.BeanState;
import io.ebean.DB;
import io.ebean.xtest.BaseTestCase;
@@ -185,9 +186,9 @@ public class TestJsonBeanDescriptorParse extends BaseTestCase {
private SpiJsonReader createRead(SpiEbeanServer server, BeanDescriptor descriptor) {
StringReader reader = new StringReader("{\"id\":123,\"name\":\"Hello Rob\"}");
- JsonParser parser = server.json().createParser(reader);
+ JsonReader parser = server.json().createParser(reader);
- return new ReadJson(descriptor, parser, null, null, false);
+ return new ReadJson(descriptor, parser, null, null, false, JsonStream.builder().build());
}
}
diff --git a/ebean-test/src/test/resources/bean/example-list-contains.json b/ebean-test/src/test/resources/bean/example-list-contains.json
index dc7599b10..5078cbc2f 100644
--- a/ebean-test/src/test/resources/bean/example-list-contains.json
+++ b/ebean-test/src/test/resources/bean/example-list-contains.json
@@ -1,9 +1,7 @@
[ {
"name": "something",
- "other": null,
"version": 1
}, {
"name": "other",
- "other": null,
"version": 1
} ]
diff --git a/ebean-test/src/test/resources/bean/example-list-match.json b/ebean-test/src/test/resources/bean/example-list-match.json
index 8c7b8b681..9c619f5f1 100644
--- a/ebean-test/src/test/resources/bean/example-list-match.json
+++ b/ebean-test/src/test/resources/bean/example-list-match.json
@@ -1,13 +1,16 @@
-[ {
- "id": "*",
- "name": "something",
- "other": null,
- "whenModified": "*",
- "version": 1
-}, {
- "id": "*",
- "name": "other",
- "other": null,
- "whenModified": "*",
- "version": 1
-} ]
+[
+ {
+ "id": "*",
+ "name": "something",
+ "other": null,
+ "whenModified": "*",
+ "version": 1
+ },
+ {
+ "id": "*",
+ "name": "other",
+ "other": null,
+ "whenModified": "*",
+ "version": 1
+ }
+]
diff --git a/pom.xml b/pom.xml
index 2ec424392..cb625c876 100644
--- a/pom.xml
+++ b/pom.xml
@@ -40,6 +40,7 @@
2.22.0
+ 3.142.2.2203.13.0