From a998c0be5584ab78ffa792cfe7921390e1aefa0d Mon Sep 17 00:00:00 2001 From: rbygrave Date: Fri, 19 Dec 2014 00:01:02 +1300 Subject: [PATCH] Fix for #226 - Json - support parsing json with unknown bean properties --- .../avaje/ebean/text/json/EJsonReader.java | 13 +++++--- .../server/deploy/BeanDescriptorJsonHelp.java | 31 ++++++++++--------- .../ebean/text/json/JsonContextTest.java | 10 ++++++ 3 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/avaje/ebean/text/json/EJsonReader.java b/src/main/java/com/avaje/ebean/text/json/EJsonReader.java index c644a9266..67f57a921 100644 --- a/src/main/java/com/avaje/ebean/text/json/EJsonReader.java +++ b/src/main/java/com/avaje/ebean/text/json/EJsonReader.java @@ -118,15 +118,20 @@ class EJsonReader { private Object parseJson(JsonToken token) throws IOException { if (token == null) { - // no initial token so expect to read START_OBJECT or similar token = parser.nextToken(); - if (JsonToken.VALUE_NULL == token) { - return null; + // if it is a simple value just return it + switch (token) { + case VALUE_NULL: 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(); } } - stack = new Stack(); // it is a object or array, process the first JsonToken + stack = new Stack(); processJsonToken(token); // process the rest of the object or array diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorJsonHelp.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorJsonHelp.java index aa3994170..25e38b559 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorJsonHelp.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorJsonHelp.java @@ -1,6 +1,7 @@ package com.avaje.ebeaninternal.server.deploy; import com.avaje.ebean.bean.EntityBean; +import com.avaje.ebean.text.json.EJson; import com.avaje.ebeaninternal.server.text.json.WriteJson; import com.avaje.ebeaninternal.server.text.json.WriteJson.WriteBean; import com.fasterxml.jackson.core.JsonParseException; @@ -50,13 +51,18 @@ public class BeanDescriptorJsonHelp { @SuppressWarnings("unchecked") public T jsonRead(JsonParser parser, String path) throws IOException { - - JsonToken token = parser.nextToken(); - if (JsonToken.VALUE_NULL == token || JsonToken.END_ARRAY == token) { - return null; - } - if (JsonToken.START_OBJECT != token) { - throw new JsonParseException("Unexpected token "+token+" - expecting start_object", parser.getCurrentLocation()); + + 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("Unexpected token "+token+" - expecting start_object", parser.getCurrentLocation()); + } } if (desc.inheritInfo == null) { @@ -66,8 +72,7 @@ public class BeanDescriptorJsonHelp { // check for the discriminator value to determine the correct sub type String discColumn = inheritInfo.getRoot().getDiscriminatorColumn(); - token = parser.nextToken(); - if (token != JsonToken.FIELD_NAME) { + if (parser.nextToken() != JsonToken.FIELD_NAME) { String msg = "Error reading inheritance discriminator - expected [" + discColumn + "] but no json key?"; throw new JsonParseException(msg, parser.getCurrentLocation()); } @@ -103,18 +108,16 @@ public class BeanDescriptorJsonHelp { protected T jsonReadProperties(JsonParser parser, EntityBean bean) throws IOException { do { - + JsonToken event = parser.nextToken(); if (JsonToken.FIELD_NAME == event) { String key = parser.getCurrentName(); BeanProperty p = desc.getBeanProperty(key); if (p != null) { p.jsonRead(parser, bean); - } else { - // Object rawValue = EJson.parse(parser); - // unknown property key ... - // ctx.readUnmappedJson(propName); + // unknown property ... read and ignore + EJson.parse(parser); } } else if (JsonToken.END_OBJECT == event) { diff --git a/src/test/java/com/avaje/ebean/text/json/JsonContextTest.java b/src/test/java/com/avaje/ebean/text/json/JsonContextTest.java index d8ef8c871..5ea2301df 100644 --- a/src/test/java/com/avaje/ebean/text/json/JsonContextTest.java +++ b/src/test/java/com/avaje/ebean/text/json/JsonContextTest.java @@ -50,6 +50,16 @@ public class JsonContextTest { assertEquals("Jim", ((Customer) bean).getName()); } + @Test + public void test_unknownProperty() { + + String jsonWithUnknown = "{\"id\":42,\"unknownProp\":\"foo\",\"name\":\"rob\",\"version\":1}"; + + Customer customer = Ebean.json().toBean(Customer.class, jsonWithUnknown); + assertEquals(Integer.valueOf(42), customer.getId()); + assertEquals("rob", customer.getName()); + } + @Test public void testCreateGenerator() throws Exception {