Skip to content

Commit

Permalink
Include property name/value when serialization fails
Browse files Browse the repository at this point in the history
  • Loading branch information
aguibert committed Aug 9, 2019
1 parent bed4fff commit a96a982
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ public enum MessageKeys {
INCOMPATIBLE_FACTORY_CREATOR_RETURN_TYPE("incompatibleFactoryCreatorReturnType"),
MULTIPLE_JSONB_CREATORS("multipleJsonbCreators"),
INTERNAL_ERROR("internalError"),
SERIALIZE_VALUE_ERROR("serializeValueError"),
SERIALIZE_PROPERTY_ERROR("serializePropertyError"),
DESERIALIZE_VALUE_ERROR("deserializeValueError"),
PARSING_NUMBER("parsingNumber"),
UNKNOWN_BINARY_DATA_STRATEGY("unknownBinaryDataStrategy"),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016, 2018 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2019 Oracle and/or its affiliates. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
Expand All @@ -15,7 +15,10 @@

import org.eclipse.yasson.internal.Marshaller;
import org.eclipse.yasson.internal.model.customization.Customization;
import org.eclipse.yasson.internal.properties.MessageKeys;
import org.eclipse.yasson.internal.properties.Messages;

import javax.json.bind.JsonbException;
import javax.json.bind.serializer.JsonbSerializer;
import javax.json.bind.serializer.SerializationContext;
import javax.json.stream.JsonGenerator;
Expand Down Expand Up @@ -48,7 +51,12 @@ public AbstractValueTypeSerializer(Customization customization) {
@Override
public void serialize(T obj, JsonGenerator generator, SerializationContext ctx) {
Marshaller marshaller = (Marshaller) ctx;
serialize(obj, generator, marshaller);
try {
serialize(obj, generator, marshaller);
} catch (Exception e) {
throw new JsonbException(Messages.getMessage(MessageKeys.SERIALIZE_VALUE_ERROR,
obj, obj.getClass().getCanonicalName(), e.getMessage()));
}
}

protected abstract void serialize(T obj, JsonGenerator generator, Marshaller marshaller);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016, 2018 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2019 Oracle and/or its affiliates. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
Expand All @@ -17,7 +17,10 @@
import org.eclipse.yasson.internal.ReflectionUtils;
import org.eclipse.yasson.internal.model.ClassModel;
import org.eclipse.yasson.internal.model.PropertyModel;
import org.eclipse.yasson.internal.properties.MessageKeys;
import org.eclipse.yasson.internal.properties.Messages;

import javax.json.bind.JsonbException;
import javax.json.bind.serializer.JsonbSerializer;
import javax.json.bind.serializer.SerializationContext;
import javax.json.stream.JsonGenerator;
Expand Down Expand Up @@ -58,7 +61,12 @@ public ObjectSerializer(CurrentItem<?> wrapper, Type runtimeType, ClassModel cla
protected void serializeInternal(T object, JsonGenerator generator, SerializationContext ctx) {
final PropertyModel[] allProperties = ((Marshaller) ctx).getMappingContext().getOrCreateClassModel(object.getClass()).getSortedProperties();
for (PropertyModel model : allProperties) {
marshallProperty(object, generator, ctx, model);
try {
marshallProperty(object, generator, ctx, model);
} catch (Exception e) {
throw new JsonbException(Messages.getMessage(MessageKeys.SERIALIZE_PROPERTY_ERROR,
model.getWriteName(), object.getClass().getCanonicalName(), model.getValue(object)), e);
}
}
}

Expand All @@ -72,7 +80,6 @@ protected void writeStart(String key, JsonGenerator generator) {
generator.writeStartObject(key);
}

@SuppressWarnings("unchecked")
private void marshallProperty(T object, JsonGenerator generator, SerializationContext ctx, PropertyModel propertyModel) {
Marshaller marshaller = (Marshaller) ctx;

Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/yasson-messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ errorCallingJsonbCreator=Exception occurred during call to JSONB creator on clas
incompatibleFactoryCreatorReturnType=Return type of creator {0} must be of type {1}.
multipleJsonbCreators=More than one @JsonbCreator declared in class {0}.
internalError=Internal error: {0}
serializeValueError=Unable to serialize value ''{0}'' of type {1} because of: {2}
serializePropertyError=Unable to serialize property ''{0}'' from {1} with value ''{2}''
deserializeValueError=Error deserialize JSON value into type: {0}.
parsingNumber=Error parsing number {0} with format {1}.
unknownBinaryDataStrategy=Unknown binary data strategy: {0}
Expand Down
66 changes: 66 additions & 0 deletions src/test/java/org/eclipse/yasson/Assertions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package org.eclipse.yasson;

import static org.junit.Assert.fail;

import java.util.function.Function;
import java.util.function.Supplier;

import javax.json.bind.JsonbException;

public class Assertions {

/**
* Asserts that the given operation will fail with a JsonbException
* @param operation The operation that is expected to fail
*/
public static void shouldFail(Supplier<?> operation) {
shouldFail(operation, JsonbException.class, msg -> true);
}

public static void shouldFail(Runnable operation) {
shouldFail(() -> {
operation.run();
return null;
});
}

/**
* Asserts that the given operation will fail with a JsonbException
* @param operation The operation that is expected to fail
* @param checkExceptionMessage Any checks that should be made on the exception message. For example, ensuring the exception
* includes a specific token.
*/
public static void shouldFail(Supplier<?> operation, Function<String,Boolean> checkExceptionMessage) {
shouldFail(operation, JsonbException.class, checkExceptionMessage);
}

/**
* Asserts that the given operation will fail
* @param operation The operation that is expected to fail
* @param expectedType The expected exception type to receive when evaluating the operation
* @param checkExceptionMessage Any checks that should be made on the exception message. For example, ensuring the exception
* includes a specific token.
*/
public static void shouldFail(Supplier<?> operation, Class<? extends Throwable> expectedType, Function<String,Boolean> checkExceptionMessage) {
try {
operation.get();
fail("The operation should have failed with a " + expectedType.getCanonicalName() + " but it succeeded.");
} catch (Throwable t) {
String fullErrorMessage = t.getMessage();
for (Throwable current = t; current.getCause() != null && current.getCause() != current; current = current.getCause()) {
fullErrorMessage += current.getMessage();
}
if (expectedType.isAssignableFrom(t.getClass())) {
if (!checkExceptionMessage.apply(fullErrorMessage)) {
t.printStackTrace();
fail("Exception did not contain the proper content: " + fullErrorMessage);
}
} else {
t.printStackTrace();
fail("Expected to get an exception of " + expectedType + " but instead was " + t.getClass());
}
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

package org.eclipse.yasson.defaultmapping.basic;

import static org.eclipse.yasson.Assertions.*;
import org.eclipse.yasson.TestTypeToken;
import org.eclipse.yasson.defaultmapping.basic.model.BigDecimalInNumber;
import org.eclipse.yasson.defaultmapping.generics.model.ScalarValueWrapper;
Expand All @@ -26,10 +27,18 @@
import javax.json.JsonWriter;
import javax.json.bind.Jsonb;
import javax.json.bind.JsonbBuilder;
import javax.json.bind.JsonbException;
import javax.json.stream.JsonGenerator;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.StringWriter;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;

/**
* @author Roman Grigoriadi
Expand Down Expand Up @@ -207,5 +216,39 @@ public void testJsonpBigNumber() {
"\"unsafeBigDecimalValue\":9223372036854775807}", w.toString());

}

public static class NumberContainer {
public Double doubleProp;
public Collection<Double> collectionProp;
public Map<String,Double> mapProp;
}

@Test
public void testSerializeInvalidDouble() {
shouldFail(() -> jsonb.toJson(Double.POSITIVE_INFINITY),
msg -> msg.contains("Unable to serialize value") && msg.contains("java.lang.Double"));

NumberContainer obj = new NumberContainer();
obj.doubleProp = Double.POSITIVE_INFINITY;
shouldFail(() -> jsonb.toJson(obj),
msg -> msg.contains("doubleProp") && msg.contains("NumberContainer"));
}


@Test
public void testSerializeInvalidDoubleCollection() {
NumberContainer obj = new NumberContainer();
obj.collectionProp = Collections.singleton(Double.POSITIVE_INFINITY);
shouldFail(() -> jsonb.toJson(obj),
msg -> msg.contains("collectionProp") && msg.contains("NumberContainer") && msg.contains("Infinity"));
}

@Test
public void testSerializeInvalidDoubleMap() {
NumberContainer obj = new NumberContainer();
obj.mapProp = Collections.singletonMap("doubleKey", Double.POSITIVE_INFINITY);
shouldFail(() -> jsonb.toJson(obj),
msg -> msg.contains("mapProp") && msg.contains("NumberContainer") && msg.contains("Infinity"));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
******************************************************************************/
package org.eclipse.yasson.jsonpsubstitution;

import org.eclipse.yasson.Assertions;
import org.eclipse.yasson.JsonBindingProvider;
import org.eclipse.yasson.TestTypeToken;
import org.eclipse.yasson.YassonJsonb;
Expand Down Expand Up @@ -165,12 +166,7 @@ public void testInvalidGeneratorWrappedWithUserInteraction() {
generator.writeStartObject();
//key not written

try {
jsonb.toJson(dog, generator);
Assert.fail("JsonbException not thrown");
} catch (JsonbException e) {
//OK
}
Assertions.shouldFail(() -> jsonb.toJson(dog, generator));
}

@Test
Expand Down

0 comments on commit a96a982

Please sign in to comment.