forked from immutables/immutables
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Issues with Gson Jackson Bridge (immutables#1120)
- Integers are printed as doubles (delegate to each specific number type method, eg `writeNumber(long`) - Allow strings for boolean in XML streaming parser
- Loading branch information
1 parent
c5404ca
commit 3e3ccc6
Showing
8 changed files
with
355 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package org.immutables.gson.stream; | ||
|
||
import com.fasterxml.jackson.core.JsonParser; | ||
import com.google.gson.stream.JsonReader; | ||
|
||
import javax.annotation.concurrent.NotThreadSafe; | ||
import java.io.IOException; | ||
|
||
/** | ||
* {@link JsonReader} implementation backed by Jackson's {@link JsonParser}. | ||
* This version assumes the token producer only supports strings, therefore will | ||
* work with the XML and properties formats. | ||
*/ | ||
@NotThreadSafe | ||
public class XmlParserReader extends JsonParserReader { | ||
public XmlParserReader(JsonParser parser) { | ||
super(parser); | ||
} | ||
|
||
@Override | ||
public boolean nextBoolean() throws IOException { | ||
return Boolean.parseBoolean(nextString()); | ||
} | ||
|
||
@Override | ||
public double nextDouble() throws IOException { | ||
return Double.parseDouble(nextString()); | ||
} | ||
|
||
@Override | ||
public long nextLong() throws IOException { | ||
return Long.parseLong(nextString()); | ||
} | ||
|
||
@Override | ||
public int nextInt() throws IOException { | ||
return Integer.parseInt(nextString()); | ||
} | ||
} |
158 changes: 158 additions & 0 deletions
158
gson/test/org/immutables/gson/bridge/GsonJacksonBridgeSerializationTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
package org.immutables.gson.bridge; | ||
|
||
import com.fasterxml.jackson.core.JsonFactory; | ||
import com.fasterxml.jackson.core.JsonGenerator; | ||
import com.fasterxml.jackson.core.JsonParser; | ||
import com.fasterxml.jackson.dataformat.cbor.CBORFactory; | ||
import com.fasterxml.jackson.dataformat.javaprop.JavaPropsFactory; | ||
import com.fasterxml.jackson.dataformat.smile.SmileFactory; | ||
import com.fasterxml.jackson.dataformat.xml.XmlFactory; | ||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; | ||
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator; | ||
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; | ||
import com.google.gson.Gson; | ||
import com.google.gson.GsonBuilder; | ||
import org.immutables.gson.stream.JsonGeneratorWriter; | ||
import org.immutables.gson.stream.JsonParserReader; | ||
import org.immutables.gson.stream.XmlParserReader; | ||
import org.junit.Assert; | ||
import org.junit.Test; | ||
|
||
import javax.xml.namespace.QName; | ||
import java.io.ByteArrayOutputStream; | ||
import java.io.IOException; | ||
import java.math.BigDecimal; | ||
import java.util.HashMap; | ||
|
||
/** | ||
* Test the various Jackson serialization formats against the Gson/Jackson bridge. | ||
*/ | ||
public class GsonJacksonBridgeSerializationTest { | ||
|
||
private final Gson gson = new GsonBuilder() | ||
.registerTypeAdapterFactory(new GsonAdaptersTestObject()) | ||
.registerTypeAdapterFactory(new GsonAdaptersTestSubObject()) | ||
.create(); | ||
|
||
private TestObject createTestObject() { | ||
return ImmutableTestObject.builder() | ||
.intVal(123) | ||
.integerVal(123) | ||
.addListOfInteger(1, 2, 3, 4, 5, 6) | ||
.longVal(2349823948398472394L) | ||
.longObjVal(2349823948398472394L) | ||
.addListOfLong(2349823948398472394L, 2349822348398472394L, 2349823948123332394L) | ||
.floatVal(123123.0980F) | ||
.floatObjVal(123123.0980F) | ||
.addListOfFloat(123123.0980F, 124234.0980F, 1233455.0980F) | ||
.doubleVal(123123123.1231231) | ||
.doubleObjVal(123123123.1231231) | ||
.addListOfDouble(123123.1231, 123123123.123213, 234234234.23423) | ||
.bigDecimalVal(new BigDecimal(4234234.1312313123)) | ||
.addListOfBigDecimal(new BigDecimal(123123.123123), new BigDecimal(3534345.345345), new BigDecimal(35252.2411)) | ||
.booleanVal(true) | ||
.booleanObjVal(false) | ||
.addListOfBoolean(true, false, true) | ||
.stringVal("This is a test") | ||
.addListOfString("a", "b", "c") | ||
.addSetOfString("a", "b", "c") | ||
.putMapOfStringToString("a", "1") | ||
.putMapOfStringToString("b", "2") | ||
.testEnumVal(TestEnum.VALUE1) | ||
.putMapOfTestEnumToString(TestEnum.VALUE2, "test2") | ||
.putMapOfTestEnumToString(TestEnum.VALUE3, "test3") | ||
.addListOfSubObject(ImmutableTestSubObject.builder() | ||
.a("Test") | ||
.b(1231) | ||
.build()) | ||
.build(); | ||
} | ||
|
||
@Test | ||
public void jsonFactoryTest() throws IOException { | ||
TestObject value = createTestObject(); | ||
JsonFactory factory = new JsonFactory(); | ||
Class<TestObject> clazz = TestObject.class; | ||
ByteArrayOutputStream outputStream = testWriting(value, factory, clazz); | ||
TestObject value2 = testReading(factory, clazz, outputStream); | ||
Assert.assertEquals(value2.toString(), value.toString()); | ||
} | ||
|
||
@Test | ||
public void xmlFactoryTest() throws IOException { | ||
TestObject value = createTestObject(); | ||
XmlFactory factory = new XmlFactory(); | ||
Class<TestObject> clazz = TestObject.class; | ||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); | ||
ToXmlGenerator g = factory.createGenerator(outputStream); | ||
g.setNextName(QName.valueOf(clazz.getAnnotation(JacksonXmlRootElement.class).localName())); | ||
JsonGeneratorWriter generatorWriter = new JsonGeneratorWriter(g); | ||
gson.toJson(value, clazz, generatorWriter); | ||
generatorWriter.flush(); | ||
TestObject value2 = testXmlReading(factory, clazz, outputStream); | ||
Assert.assertEquals(value2.toString(), value.toString()); | ||
} | ||
|
||
@Test | ||
public void yamlFactoryTest() throws IOException { | ||
TestObject value = createTestObject(); | ||
YAMLFactory factory = new YAMLFactory(); | ||
Class<TestObject> clazz = TestObject.class; | ||
ByteArrayOutputStream outputStream = testWriting(value, factory, clazz); | ||
TestObject value2 = testReading(factory, clazz, outputStream); | ||
Assert.assertEquals(value2.toString(), value.toString()); | ||
} | ||
|
||
@Test | ||
public void smileFactoryTest() throws IOException { | ||
TestObject value = createTestObject(); | ||
SmileFactory factory = new SmileFactory(); | ||
Class<TestObject> clazz = TestObject.class; | ||
ByteArrayOutputStream outputStream = testWriting(value, factory, clazz); | ||
TestObject value2 = testReading(factory, clazz, outputStream); | ||
Assert.assertEquals(value2.toString(), value.toString()); | ||
} | ||
|
||
@Test | ||
public void propertiesFactoryTest() throws IOException { | ||
TestObject value = ImmutableTestObject.copyOf(createTestObject()) | ||
// excluding map here because when it is de-serialized, the order is changed and the unit test fails | ||
.withMapOfStringToString(new HashMap<String, String>()); | ||
JavaPropsFactory factory = new JavaPropsFactory(); | ||
Class<TestObject> clazz = TestObject.class; | ||
ByteArrayOutputStream outputStream = testWriting(value, factory, clazz); | ||
TestObject value2 = testXmlReading(factory, clazz, outputStream); | ||
Assert.assertEquals(value2.toString(), value.toString()); | ||
} | ||
|
||
@Test | ||
public void cborFactoryTest() throws IOException { | ||
TestObject value = createTestObject(); | ||
CBORFactory factory = new CBORFactory(); | ||
Class<TestObject> clazz = TestObject.class; | ||
ByteArrayOutputStream outputStream = testWriting(value, factory, clazz); | ||
TestObject value2 = testReading(factory, clazz, outputStream); | ||
Assert.assertEquals(value2.toString(), value.toString()); | ||
} | ||
|
||
private ByteArrayOutputStream testWriting(TestObject value, JsonFactory factory, Class<TestObject> clazz) throws IOException { | ||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); | ||
JsonGenerator g = factory.createGenerator(outputStream); | ||
JsonGeneratorWriter generatorWriter = new JsonGeneratorWriter(g); | ||
gson.toJson(value, clazz, generatorWriter); | ||
generatorWriter.flush(); | ||
return outputStream; | ||
} | ||
|
||
private TestObject testReading(JsonFactory factory, Class<TestObject> clazz, ByteArrayOutputStream outputStream) throws IOException { | ||
JsonParser r = factory.createParser(outputStream.toByteArray()); | ||
JsonParserReader parserReader = new JsonParserReader(r); | ||
return gson.fromJson(parserReader, clazz); | ||
} | ||
|
||
private TestObject testXmlReading(JsonFactory factory, Class<TestObject> clazz, ByteArrayOutputStream outputStream) throws IOException { | ||
JsonParser r = factory.createParser(outputStream.toByteArray()); | ||
JsonParserReader parserReader = new XmlParserReader(r); | ||
return gson.fromJson(parserReader, clazz); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package org.immutables.gson.bridge; | ||
|
||
public enum TestEnum { | ||
VALUE1, VALUE2, VALUE3 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package org.immutables.gson.bridge; | ||
|
||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; | ||
import org.immutables.gson.Gson; | ||
import org.immutables.value.Value; | ||
|
||
import java.math.BigDecimal; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Set; | ||
|
||
@Gson.TypeAdapters | ||
@Value.Immutable | ||
@JacksonXmlRootElement(localName = "test-object") | ||
public interface TestObject { | ||
int intVal(); | ||
|
||
Integer integerVal(); | ||
|
||
List<Integer> listOfInteger(); | ||
|
||
long longVal(); | ||
|
||
Long longObjVal(); | ||
|
||
List<Long> listOfLong(); | ||
|
||
float floatVal(); | ||
|
||
Float floatObjVal(); | ||
|
||
List<Float> listOfFloat(); | ||
|
||
double doubleVal(); | ||
|
||
Double doubleObjVal(); | ||
|
||
List<Double> listOfDouble(); | ||
|
||
BigDecimal bigDecimalVal(); | ||
|
||
List<BigDecimal> listOfBigDecimal(); | ||
|
||
boolean booleanVal(); | ||
|
||
Boolean booleanObjVal(); | ||
|
||
List<Boolean> listOfBoolean(); | ||
|
||
String stringVal(); | ||
|
||
List<String> listOfString(); | ||
|
||
Set<String> setOfString(); | ||
|
||
Map<String, String> mapOfStringToString(); | ||
|
||
TestEnum testEnumVal(); | ||
|
||
List<TestEnum> listOfTestEnum(); | ||
|
||
Map<TestEnum, String> mapOfTestEnumToString(); | ||
|
||
List<TestSubObject> listOfSubObject(); | ||
} |
Oops, something went wrong.