diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java index 9d5f484a2..f3e1b3feb 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java @@ -2337,24 +2337,31 @@ public class BeanDescriptor { return jsonReadObject(ctx, path); } else { - // read the discriminator value to determine the correct sub type + + // check for the discriminator value to determine the correct sub type String discColumn = inheritInfo.getRoot().getDiscriminatorColumn(); if (!ctx.readKeyNext()) { String msg = "Error reading inheritance discriminator - expected [" + discColumn + "] but no json key?"; throw new TextException(msg); } - String propName = ctx.getTokenKey(); - - if (!propName.equalsIgnoreCase(discColumn)) { - String msg = "Error reading inheritance discriminator - expected [" + discColumn + "] but read [" + propName + "]"; - throw new TextException(msg); - } - - String discValue = ctx.readScalarValue(); - if (!ctx.readValueNext()) { - String msg = "Error reading inheritance discriminator [" + discColumn + "]. Expected more json name values?"; - throw new TextException(msg); + + String propName = ctx.getTokenKey(); + String discValue; + if (propName.equalsIgnoreCase(discColumn)) { + discValue = ctx.readScalarValue(); + if (!ctx.readValueNext()) { + // Expected to read a comma to setup for reading the real properties of the bean + String msg = "Error reading inheritance discriminator [" + discColumn + "]. Expected more json name values?"; + throw new TextException(msg); + } + + } else { + // Assume that the we are just reading using this bean type + // Push the token key back so that it is re-read as it is one + // of the real properties of the bean itself + ctx.pushTokenKey(); + discValue = inheritInfo.getDiscriminatorStringValue(); } // determine the sub type for this particular json object diff --git a/src/main/java/com/avaje/ebeaninternal/server/text/json/ReadBasicJsonContext.java b/src/main/java/com/avaje/ebeaninternal/server/text/json/ReadBasicJsonContext.java index caefcb7ad..f35864db7 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/text/json/ReadBasicJsonContext.java +++ b/src/main/java/com/avaje/ebeaninternal/server/text/json/ReadBasicJsonContext.java @@ -8,10 +8,18 @@ public class ReadBasicJsonContext implements ReadJsonInterface { private char tokenStart; private String tokenKey; + private boolean pushedTokenKey; public ReadBasicJsonContext(ReadJsonSource src) { this.src = src; } + + /** + * Push the current token key back onto the 'stack'. + */ + public void pushTokenKey() { + pushedTokenKey = true; + } public char getToken() { return tokenStart; @@ -84,7 +92,13 @@ public class ReadBasicJsonContext implements ReadJsonInterface { } public void readNextToken() { - + + if (pushedTokenKey) { + // Do nothing + pushedTokenKey = false; + return; + } + ignoreWhiteSpace(); tokenStart = src.nextChar("EOF finding next token"); diff --git a/src/main/java/com/avaje/ebeaninternal/server/text/json/ReadJsonContext.java b/src/main/java/com/avaje/ebeaninternal/server/text/json/ReadJsonContext.java index bcca60b9b..1d75ba806 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/text/json/ReadJsonContext.java +++ b/src/main/java/com/avaje/ebeaninternal/server/text/json/ReadJsonContext.java @@ -179,4 +179,6 @@ public class ReadJsonContext extends ReadBasicJsonContext { } + + } diff --git a/src/test/java/com/avaje/tests/model/basic/Animal.java b/src/test/java/com/avaje/tests/model/basic/Animal.java new file mode 100644 index 000000000..d92a6a982 --- /dev/null +++ b/src/test/java/com/avaje/tests/model/basic/Animal.java @@ -0,0 +1,38 @@ +package com.avaje.tests.model.basic; + +import javax.persistence.DiscriminatorColumn; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; +import javax.persistence.Table; +import javax.persistence.Version; + +@Entity +@Table(name = "animals") +@Inheritance(strategy = InheritanceType.SINGLE_TABLE) +@DiscriminatorColumn(name = "species") +public abstract class Animal { + + @Id + Long id; + + @Version + Long version; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getVersion() { + return version; + } + + public void setVersion(Long version) { + this.version = version; + } +} diff --git a/src/test/java/com/avaje/tests/model/basic/Cat.java b/src/test/java/com/avaje/tests/model/basic/Cat.java new file mode 100644 index 000000000..8f74c7319 --- /dev/null +++ b/src/test/java/com/avaje/tests/model/basic/Cat.java @@ -0,0 +1,20 @@ +package com.avaje.tests.model.basic; + +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; + +@Entity +@DiscriminatorValue("CAT") +public class Cat extends Animal { + + String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} diff --git a/src/test/java/com/avaje/tests/model/basic/Dog.java b/src/test/java/com/avaje/tests/model/basic/Dog.java new file mode 100644 index 000000000..3b9c4b287 --- /dev/null +++ b/src/test/java/com/avaje/tests/model/basic/Dog.java @@ -0,0 +1,32 @@ +package com.avaje.tests.model.basic; + +import java.sql.Date; + +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; + +@Entity +@DiscriminatorValue("DOG") +public class Dog extends Animal { + + String registrationNumber; + + Date dateOfBirth; + + public String getRegistrationNumber() { + return registrationNumber; + } + + public void setRegistrationNumber(String registrationNumber) { + this.registrationNumber = registrationNumber; + } + + public Date getDateOfBirth() { + return dateOfBirth; + } + + public void setDateOfBirth(Date dateOfBirth) { + this.dateOfBirth = dateOfBirth; + } + +} diff --git a/src/test/java/com/avaje/tests/text/json/TestJsonInheritanceDiscriminator.java b/src/test/java/com/avaje/tests/text/json/TestJsonInheritanceDiscriminator.java new file mode 100644 index 000000000..6f486ad4b --- /dev/null +++ b/src/test/java/com/avaje/tests/text/json/TestJsonInheritanceDiscriminator.java @@ -0,0 +1,62 @@ +package com.avaje.tests.text.json; + +import java.sql.Date; +import java.util.List; + +import junit.framework.TestCase; + +import com.avaje.ebean.Ebean; +import com.avaje.ebean.text.json.JsonContext; +import com.avaje.tests.model.basic.Animal; +import com.avaje.tests.model.basic.Cat; +import com.avaje.tests.model.basic.Dog; + +public class TestJsonInheritanceDiscriminator extends TestCase { + + public void testNoDiscriminator() { + + Cat cat = new Cat(); + cat.setName("Gemma"); + + Ebean.save(cat); + + JsonContext json = Ebean.createJsonContext(); + String jsonContent = json.toJsonString(cat); + + Cat cat2 = json.toBean(Cat.class, jsonContent); + + assertEquals(cat.getId(), cat2.getId()); + assertEquals(cat.getName(), cat2.getName()); + assertEquals(cat.getVersion(), cat2.getVersion()); + + + String noDiscriminator = "{\"id\":1,\"name\":\"Gemma\",\"version\":1}"; + + Cat cat3 = json.toBean(Cat.class, noDiscriminator); + + assertEquals(cat.getId(), cat3.getId()); + assertEquals(cat.getName(), cat3.getName()); + assertEquals(cat.getVersion(), cat3.getVersion()); + + + Dog dog = new Dog(); + dog.setRegistrationNumber("ABC123"); + dog.setDateOfBirth(new Date(System.currentTimeMillis())); + + Ebean.save(dog); + + List animals = Ebean.find(Animal.class).findList(); + + String listJson = json.toJsonString(animals, false); + + List animals2 = json.toList(Animal.class, listJson); + assertEquals(animals.size(), animals2.size()); + + String noDiscList = "[{\"id\":1,\"name\":\"Gemma\",\"version\":1},{\"name\":\"PussCat\",\"version\":1},{\"species\":\"CAT\",\"name\":\"PussCat\",\"version\":1}]"; + List cats = json.toList(Cat.class, noDiscList); + assertEquals(cats.size(), 3); + + + } + +}