@JsonbPropertyOrder is now applied on property read name instead of a bean name. (#167)
Signed-off-by: Roman Grigoriadi <roman.grigoriadi@oracle.com>
diff --git a/src/main/java/org/eclipse/yasson/internal/ClassParser.java b/src/main/java/org/eclipse/yasson/internal/ClassParser.java
index 25b1069..540c9c3 100644
--- a/src/main/java/org/eclipse/yasson/internal/ClassParser.java
+++ b/src/main/java/org/eclipse/yasson/internal/ClassParser.java
@@ -34,8 +34,10 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
import java.util.Objects;
+
/**
* Created a class internal model.
*
@@ -65,16 +67,29 @@
parseClassAndInterfaceMethods(classElement, classProperties);
//add sorted properties from parent, if they are not overridden in current class
- final List<PropertyModel> sortedProperties = getSortedParentProperties(classModel, classElement, classProperties);
- //sort and add properties from current class
- sortedProperties.addAll(jsonbContext.getConfigProperties().getPropertyOrdering().orderProperties(classProperties, classModel, jsonbContext));
+ //parent properties are by default first by alphabet, than properties from a subclass
+ final List<PropertyModel> sortedParentProperties = getSortedParentProperties(classModel, classElement, classProperties);
- checkPropertyNameClash(sortedProperties, classModel.getType());
+ List<PropertyModel> classPropertyModels = classProperties.values().stream()
+ .map(property -> new PropertyModel(classModel, property, jsonbContext))
+ .collect(Collectors.toList());
+
+ //check for collision on same property read name
+ List<PropertyModel> unsortedMerged = new ArrayList<>();
+ unsortedMerged.addAll(sortedParentProperties);
+ unsortedMerged.addAll(classPropertyModels);
+ checkPropertyNameClash(unsortedMerged, classModel.getType());
+
+
+ List<PropertyModel> sortedPropertyModels = new ArrayList<>();
+ sortedPropertyModels.addAll(sortedParentProperties);
+ sortedPropertyModels.addAll(jsonbContext.getConfigProperties().getPropertyOrdering()
+ .orderProperties(classPropertyModels, classModel));
//reference property to creator parameter by name to merge configuration in runtime
JsonbCreator creator = classModel.getClassCustomization().getCreator();
if (creator != null) {
- sortedProperties.forEach((propertyModel -> {
+ sortedPropertyModels.forEach((propertyModel -> {
for (CreatorModel creatorModel : creator.getParams()) {
if (creatorModel.getName().equals(propertyModel.getPropertyName())) {
CreatorCustomization customization = (CreatorCustomization) creatorModel.getCustomization();
@@ -83,7 +98,8 @@
}
}));
}
- classModel.setProperties(sortedProperties);
+
+ classModel.setProperties(sortedPropertyModels);
}
@@ -216,9 +232,9 @@
for (PropertyModel checkedPropertyModel : checkedProperties) {
if ((checkedPropertyModel.getReadName().equals(collectedPropertyModel.getReadName())
- && checkedPropertyModel.isReadable() && collectedPropertyModel.isReadable()) ||
+ && checkedPropertyModel.isReadable() && collectedPropertyModel.isReadable()) ||
(checkedPropertyModel.getWriteName().equals(collectedPropertyModel.getWriteName()))
- && checkedPropertyModel.isWritable() && collectedPropertyModel.isWritable()) {
+ && checkedPropertyModel.isWritable() && collectedPropertyModel.isWritable()) {
throw new JsonbException(Messages.getMessage(MessageKeys.PROPERTY_NAME_CLASH,
checkedPropertyModel.getPropertyName(), collectedPropertyModel.getPropertyName(),
cls.getName()));
@@ -232,13 +248,13 @@
* Merges current class properties with parent class properties.
* If javabean property is declared in more than one inheritance levels,
* merge field, getters and setters of that property.
- *
+ * <p>
* For example BaseClass contains field foo and getter getFoo. In BaseExtensions there is a setter setFoo.
* All three will be merged for BaseExtension.
- *
+ * <p>
* Such property is sorted based on where its getter or field is located.
*/
- private List<PropertyModel> getSortedParentProperties(ClassModel classModel, JsonbAnnotatedElement<Class<?>> classElement, Map<String, Property> classProperties) {
+ private List<PropertyModel> getSortedParentProperties(ClassModel classModel, JsonbAnnotatedElement<Class<?>> classElement, Map<String, Property> classProperties) {
List<PropertyModel> sortedProperties = new ArrayList<>();
//Pull properties from parent
if (classModel.getParentClassModel() != null) {
@@ -280,10 +296,8 @@
* <li> returns current otherwise</li>
* </ul>
*
- *
* @param current current 'child' implementation
* @param parent parent implementation
- *
* @return effective method to register as getter or setter
*/
private Method selectMostSpecificNonDefaultMethod(Method current, Method parent) {
diff --git a/src/main/java/org/eclipse/yasson/internal/model/customization/ordering/PropertyOrdering.java b/src/main/java/org/eclipse/yasson/internal/model/customization/ordering/PropertyOrdering.java
index 912d8b1..31e0954 100644
--- a/src/main/java/org/eclipse/yasson/internal/model/customization/ordering/PropertyOrdering.java
+++ b/src/main/java/org/eclipse/yasson/internal/model/customization/ordering/PropertyOrdering.java
@@ -12,16 +12,16 @@
******************************************************************************/
package org.eclipse.yasson.internal.model.customization.ordering;
-import org.eclipse.yasson.internal.JsonbContext;
import org.eclipse.yasson.internal.model.ClassModel;
-import org.eclipse.yasson.internal.model.Property;
import org.eclipse.yasson.internal.model.PropertyModel;
import javax.json.bind.JsonbConfig;
import javax.json.bind.config.PropertyOrderStrategy;
-import java.util.*;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
/**
* Order properties in bean object. {@link javax.json.bind.annotation.JsonbPropertyOrder} have always precedence.
@@ -49,30 +49,27 @@
*
* @param properties Properties to sort.
* @param classModel Class model.
- * @param jsonbContext jsonb context.
* @return Sorted list of properties.
*/
- public List<PropertyModel> orderProperties(Map<String, Property> properties, ClassModel classModel, JsonbContext jsonbContext) {
+ public List<PropertyModel> orderProperties(List<PropertyModel> properties, ClassModel classModel) {
+ Map<String, PropertyModel> byReadName = new HashMap<>();
+ properties.stream().forEach(propertyModel -> byReadName.put(propertyModel.getReadName(), propertyModel));
+
String[] order = classModel.getClassCustomization().getPropertyOrder();
List<PropertyModel> sortedProperties = new ArrayList<>();
if (order != null) {
//if @JsonbPropertyOrder annotation is defined on a class
for (String propName : order) {
- final Property remove = properties.remove(propName);
+ final PropertyModel remove = byReadName.remove(propName);
if (remove != null) {
- sortedProperties.add(new PropertyModel(classModel, remove, jsonbContext));
+ sortedProperties.add(remove);
}
}
}
- //No annotation or not ordered properties remains, check JsonbConfig for ordering strategy use LEXICOGRAPHICAL as default
- return Stream.of(sortedProperties,
- propertyOrderStrategy.sortProperties(
- properties.values().stream()
- .map((prop) -> new PropertyModel(classModel, prop, jsonbContext))
- .collect(Collectors.toList())))
- .flatMap(Collection::stream)
- .collect(Collectors.toList());
+ sortedProperties.addAll(propertyOrderStrategy.sortProperties(byReadName.values()));
+ return sortedProperties;
+
}
/**
diff --git a/src/test/java/org/eclipse/yasson/customization/PropertyOrderTest.java b/src/test/java/org/eclipse/yasson/customization/PropertyOrderTest.java
index 594d8ae..844f5e7 100644
--- a/src/test/java/org/eclipse/yasson/customization/PropertyOrderTest.java
+++ b/src/test/java/org/eclipse/yasson/customization/PropertyOrderTest.java
@@ -13,13 +13,21 @@
package org.eclipse.yasson.customization;
-import org.eclipse.yasson.customization.model.*;
+import org.eclipse.yasson.customization.model.FieldCustomOrder;
+import org.eclipse.yasson.customization.model.FieldCustomOrderWrapper;
+import org.eclipse.yasson.customization.model.FieldOrder;
+import org.eclipse.yasson.customization.model.FieldOrderNameAnnotation;
+import org.eclipse.yasson.customization.model.FieldSpecificOrder;
+import org.eclipse.yasson.customization.model.RenamedPropertiesContainer;
import org.junit.Assert;
import org.junit.Test;
import javax.json.bind.Jsonb;
import javax.json.bind.JsonbBuilder;
import javax.json.bind.JsonbConfig;
+import javax.json.bind.annotation.JsonbCreator;
+import javax.json.bind.annotation.JsonbProperty;
+import javax.json.bind.annotation.JsonbPropertyOrder;
import javax.json.bind.config.PropertyOrderStrategy;
import static org.junit.Assert.assertEquals;
@@ -88,4 +96,34 @@
RenamedPropertiesContainer unmarshalledObject = jsonb.fromJson("{ \"first\" : 1, \"second\" : \"Test String\", \"third\" : 1 }", RenamedPropertiesContainer.class);
Assert.assertEquals(3, unmarshalledObject.getIntInstance());
}
+
+ @Test
+ public void testJsonbPropertyOrderOnRenamedProperties() {
+ Jsonb jsonb = JsonbBuilder.create();
+ Assert.assertEquals("{\"from\":10,\"count\":11}", jsonb.toJson(new Range(10, 11)));
+ }
+
+ @JsonbPropertyOrder(
+ {
+ "from",
+ "count"
+ }
+ )
+ public class Range {
+
+ @JsonbProperty("from")
+ public final int fromIndex;
+
+ @JsonbProperty("count")
+ public final int numberOfItems;
+
+ @JsonbCreator
+ public Range(
+ @JsonbProperty("from") int fromIndex,
+ @JsonbProperty("count") int numberOfItems
+ ) {
+ this.fromIndex = fromIndex;
+ this. numberOfItems = numberOfItems;
+ }
+ }
}