| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.johnzon.jsonb; |
| |
| import static java.util.Collections.singletonMap; |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertTrue; |
| |
| import java.lang.reflect.Type; |
| import java.util.ArrayList; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Objects; |
| import java.util.UUID; |
| |
| import jakarta.json.bind.Jsonb; |
| import jakarta.json.bind.JsonbBuilder; |
| import jakarta.json.bind.JsonbConfig; |
| import jakarta.json.bind.annotation.JsonbTransient; |
| import jakarta.json.bind.annotation.JsonbTypeDeserializer; |
| import jakarta.json.bind.annotation.JsonbTypeSerializer; |
| import jakarta.json.bind.config.PropertyOrderStrategy; |
| import jakarta.json.bind.serializer.DeserializationContext; |
| import jakarta.json.bind.serializer.JsonbDeserializer; |
| import jakarta.json.bind.serializer.JsonbSerializer; |
| import jakarta.json.bind.serializer.SerializationContext; |
| import jakarta.json.stream.JsonGenerator; |
| import jakarta.json.stream.JsonParser; |
| |
| import org.apache.johnzon.jsonb.model.Holder; |
| import org.apache.johnzon.jsonb.test.JsonbRule; |
| import org.junit.Rule; |
| import org.junit.Test; |
| |
| public class SerializerTest { |
| @Rule |
| public final JsonbRule jsonb = new JsonbRule() |
| .withPropertyOrderStrategy(PropertyOrderStrategy.LEXICOGRAPHICAL); |
| |
| @Test // https://issues.apache.org/jira/browse/JOHNZON-335 |
| public void testNestedSerializer() { |
| final String s = jsonb.toJson(new OuterTestModel()); |
| assertEquals("{\"foo\":\"generated in outer serializer\",\"inner\":{\"bar\":\"generated in inner serializer\"}}", s); |
| } |
| |
| @Test |
| public void passthroughSerializer() { |
| final NameHolder nameHolder = new NameHolder(); |
| nameHolder.name = new Named(); |
| nameHolder.name.name = "Test String"; |
| nameHolder.name.detailName = new DetailName(); |
| nameHolder.name.detailName.name = "Another Test String"; |
| assertEquals( |
| "{\"detailName\":{\"name\":\"Another Test String\",\"detail\":true},\"name\":{\"name\":\"Test String\"}}", |
| jsonb.toJson(nameHolder)); |
| |
| } |
| |
| @Test |
| public void typeSerializer() { |
| final HolderHolder container = new HolderHolder(); |
| final StringHolder instance = new StringHolder(); |
| instance.setInstance("Test String"); |
| container.setInstance(instance); |
| |
| final String json = jsonb.toJson(container); |
| assertTrue(json, json.matches( |
| "\\{\\s*\"instance\"\\s*:\\s*\\{\\s*\"instance\"\\s*:\\s*\"Test String Serialized\"\\s*}\\s*}")); |
| |
| final HolderHolder unmarshalledObject = jsonb.fromJson("{ \"instance\" : { \"instance\" : \"Test String\" } }", HolderHolder.class); |
| assertEquals("Test String Deserialized", unmarshalledObject.getInstance().getInstance()); |
| } |
| |
| @Test |
| public void arrayTypes() { |
| final ArrayHolder container = new ArrayHolder(); |
| final StringHolder instance1 = new StringHolder(); |
| instance1.setInstance("Test String 1"); |
| final StringHolder instance2 = new StringHolder(); |
| instance2.setInstance("Test String 2"); |
| container.setInstance(new StringHolder[] { instance1, instance2 }); |
| |
| final String json = jsonb.toJson(container); |
| assertEquals("{\"instance\":[{\"instance\":\"Test String 1\"},{\"instance\":\"Test String 2\"}]}", json); |
| |
| final ArrayHolder unmarshalledObject = jsonb.fromJson( |
| "{ \"instance\" : [ { \"instance\" : \"Test String 1\" }, { \"instance\" : \"Test String 2\" } ] }", |
| ArrayHolder.class); |
| assertEquals("Test String 1", unmarshalledObject.getInstance()[0].getInstance()); |
| } |
| |
| |
| @Test |
| public void roundTrip() { |
| final Jsonb jsonb = JsonbBuilder.create(); |
| |
| final String expectedJson = "{\"foo\":{\"full\":true,\"name\":\"SerializerTest\"},\"moreFoos\":[{\"full\":true,\"name\":\"foo2\"},{\"full\":true,\"name\":\"foo3\"}]}"; |
| |
| final Foo foo = new Foo(); |
| foo.name = "SerializerTest"; |
| final Wrapper wrapper = new Wrapper(); |
| wrapper.foo = foo; |
| |
| Foo foo2 = new Foo(); |
| foo2.name = "foo2"; |
| Foo foo3 = new Foo(); |
| foo3.name = "foo3"; |
| wrapper.moreFoos.add(foo2); |
| wrapper.moreFoos.add(foo3); |
| |
| assertEquals(expectedJson, jsonb.toJson(wrapper)); |
| |
| final Wrapper deser = jsonb.fromJson(expectedJson, Wrapper.class); |
| assertEquals(foo.name, deser.foo.name); |
| assertEquals(foo.name.length(), deser.foo.value); |
| assertTrue(deser.foo.flag); |
| |
| assertEquals(2, deser.moreFoos.size()); |
| assertEquals("foo2", deser.moreFoos.get(0).name); |
| assertEquals(4, deser.moreFoos.get(0).value); |
| assertEquals(4, deser.moreFoos.get(1).value); |
| } |
| |
| @Test |
| public void nullValuesInList() { |
| Jsonb jsonb = JsonbBuilder.create(); |
| |
| IntList wrapper = new IntList(); |
| wrapper.elems.add(null); |
| assertEquals("{\"elems\":[null]}", jsonb.toJson(wrapper)); |
| |
| wrapper.elems.add(1); |
| assertEquals("{\"elems\":[null,1]}", jsonb.toJson(wrapper)); |
| |
| wrapper.elems.add(0, 2); |
| assertEquals("{\"elems\":[2,null,1]}", jsonb.toJson(wrapper)); |
| |
| wrapper.elems.remove(2); |
| assertEquals("{\"elems\":[2,null]}", jsonb.toJson(wrapper)); |
| } |
| |
| @Test |
| public void nullValuesInEnumList() { |
| Jsonb jsonb = JsonbBuilder.create(); |
| |
| EnumList wrapper = new EnumList(); |
| wrapper.elems.add(null); |
| assertEquals("{\"elems\":[null]}", jsonb.toJson(wrapper)); |
| |
| wrapper.elems.add(MyStatus.OK); |
| assertEquals("{\"elems\":[null,\"OK\"]}", jsonb.toJson(wrapper)); |
| |
| wrapper.elems.add(0, MyStatus.WRONG); |
| assertEquals("{\"elems\":[\"WRONG\",null,\"OK\"]}", jsonb.toJson(wrapper)); |
| |
| wrapper.elems.remove(2); |
| assertEquals("{\"elems\":[\"WRONG\",null]}", jsonb.toJson(wrapper)); |
| } |
| |
| @Test |
| public void uuid() throws Exception { |
| final Jsonb jsonb = JsonbBuilder.create(); |
| final UUIDWrapper wrapper = new UUIDWrapper(); |
| wrapper.uuid = UUID.randomUUID(); |
| assertEquals("{\"uuid\":\"" + wrapper.uuid + "\"}", jsonb.toJson(wrapper)); |
| jsonb.close(); |
| } |
| |
| @Test |
| public void serializeWithKey() throws Exception { |
| final Jsonb jsonb = JsonbBuilder.create(); |
| final MyWrapper wrapper = new MyWrapper(); |
| wrapper.myWrapper = new MyWrapper(); |
| wrapper.myWrapper.map = singletonMap("a", "b"); |
| assertEquals("{\"myWrapper\":{\"a\":\"b\"}}", jsonb.toJson(wrapper)); |
| jsonb.close(); |
| } |
| |
| @Test |
| public void fromConfig() throws Exception { |
| try (final Jsonb jsonb = JsonbBuilder.create(new JsonbConfig() |
| .withSerializers(new AnimalSerializer()).withDeserializers(new AnimalDeserializer()))) { |
| final Animals animals = new Animals(); |
| animals.animals.add(new Cat(5, "Garfield", 10.5f, true, true)); |
| animals.animals.add(new Dog(3, "Milo", 5.5f, false, true)); |
| animals.animals.add(new Animal(6, "Tweety", 0.5f, false)); |
| |
| final String jsonString = jsonb.toJson(animals); |
| assertEquals("{\"animals\":[" + |
| "{\"type\":\"cat\",\"cuddly\":true,\"age\":5,\"furry\":true,\"name\":\"Garfield\",\"weight\":10.5}," + |
| "{\"type\":\"dog\",\"barking\":true,\"age\":3,\"furry\":false,\"name\":\"Milo\",\"weight\":5.5}," + |
| "{\"type\":\"animal\",\"age\":6,\"furry\":false,\"name\":\"Tweety\",\"weight\":0.5}]}", |
| jsonString); |
| |
| final Animals deserialized = jsonb.fromJson("{ \"animals\" : [ " |
| + "{ \"type\" : \"cat\", \"cuddly\" : true, \"age\" : 5, \"furry\" : true, \"name\" : \"Garfield\" , \"weight\" : 10.5}, " |
| + "{ \"type\" : \"dog\", \"barking\" : true, \"age\" : 3, \"furry\" : false, \"name\" : \"Milo\", \"weight\" : 5.5}, " |
| + "{ \"type\" : \"animal\", \"age\" : 6, \"furry\" : false, \"name\" : \"Tweety\", \"weight\" : 0.5}" |
| + " ] }", Animals.class); |
| assertEquals(animals.animals, deserialized.animals); |
| } |
| } |
| |
| @Test |
| public void fromAnnotation() { |
| final AnimalsAnnotation animals = new AnimalsAnnotation(); |
| animals.animals.add(new Cat(5, "Garfield", 10.5f, true, true)); |
| animals.animals.add(new Dog(3, "Milo", 5.5f, false, true)); |
| animals.animals.add(new Animal(6, "Tweety", 0.5f, false)); |
| |
| final String jsonString = jsonb.toJson(animals); |
| assertEquals("{\"animals\":[" + |
| "{\"type\":\"cat\",\"cuddly\":true,\"age\":5,\"furry\":true,\"name\":\"Garfield\",\"weight\":10.5}," + |
| "{\"type\":\"dog\",\"barking\":true,\"age\":3,\"furry\":false,\"name\":\"Milo\",\"weight\":5.5}," + |
| "{\"type\":\"animal\",\"age\":6,\"furry\":false,\"name\":\"Tweety\",\"weight\":0.5}]}", jsonString); |
| |
| final AnimalsAnnotation deserialized = jsonb.fromJson("{ \"animals\" : [ " |
| + "{ \"type\" : \"cat\", \"cuddly\" : true, \"age\" : 5, \"furry\" : true, \"name\" : \"Garfield\" , \"weight\" : 10.5}, " |
| + "{ \"type\" : \"dog\", \"barking\" : true, \"age\" : 3, \"furry\" : false, \"name\" : \"Milo\", \"weight\" : 5.5}, " |
| + "{ \"type\" : \"animal\", \"age\" : 6, \"furry\" : false, \"name\" : \"Tweety\", \"weight\" : 0.5}" |
| + " ] }", AnimalsAnnotation.class); |
| assertEquals(animals.animals, deserialized.animals); |
| } |
| |
| public static class Animal { |
| public int age; |
| public String name; |
| public float weight; |
| public boolean furry; |
| |
| public Animal() { |
| // no-op |
| } |
| |
| public Animal(int age, String name, float weight, boolean furry) { |
| this.age = age; |
| this.name = name; |
| this.weight = weight; |
| this.furry = furry; |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (this == o) { |
| return true; |
| } |
| if (o == null || getClass() != o.getClass()) { |
| return false; |
| } |
| final Animal animal = (Animal) o; |
| return age == animal.age && |
| Float.compare(animal.weight, weight) == 0 && |
| furry == animal.furry && |
| Objects.equals(name, animal.name); |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(age, name, weight, furry); |
| } |
| } |
| |
| public static class Dog extends Animal { |
| public boolean barking; |
| |
| public Dog() { |
| // no-op |
| } |
| |
| public Dog(int age, String name, float weight, boolean furry, |
| boolean barking) { |
| super(age, name, weight, furry); |
| this.barking = barking; |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (this == o) { |
| return true; |
| } |
| if (o == null || getClass() != o.getClass()) { |
| return false; |
| } |
| if (!super.equals(o)) { |
| return false; |
| } |
| final Dog dog = (Dog) o; |
| return barking == dog.barking; |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(super.hashCode(), barking); |
| } |
| } |
| |
| public static class Cat extends Animal { |
| public boolean cuddly; |
| |
| public Cat() { |
| // no-op |
| } |
| |
| public Cat(int age, String name, float weight, boolean furry, |
| boolean cuddly) { |
| super(age, name, weight, furry); |
| this.cuddly = cuddly; |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (this == o) { |
| return true; |
| } |
| if (o == null || getClass() != o.getClass()) { |
| return false; |
| } |
| if (!super.equals(o)) { |
| return false; |
| } |
| final Cat cat = (Cat) o; |
| return cuddly == cat.cuddly; |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(super.hashCode(), cuddly); |
| } |
| } |
| |
| public static class AnimalListDeserializer implements JsonbDeserializer<List<Animal>> { |
| private final AnimalDeserializer animalDeserializer = new AnimalDeserializer(); |
| |
| @Override |
| public List<Animal> deserialize(final JsonParser parser, |
| final DeserializationContext ctx, |
| final Type type) { |
| final List<Animal> animals = new ArrayList<>(); |
| while (parser.hasNext()) { |
| JsonParser.Event event = parser.next(); |
| while (event == JsonParser.Event.START_OBJECT) { |
| animals.add(animalDeserializer.deserialize(parser, ctx, type)); |
| event = parser.next(); |
| } |
| } |
| return animals; |
| } |
| } |
| |
| public static class AnimalListSerializer implements JsonbSerializer<List<Animal>> { |
| private final AnimalSerializer animalSerializer = new AnimalSerializer(); |
| |
| @Override |
| public void serialize(final List<Animal> animals, final JsonGenerator gen, |
| final SerializationContext ctx) { |
| gen.writeStartArray(); |
| for (final Animal animal : animals) { |
| animalSerializer.serialize(animal, gen, ctx); |
| } |
| gen.writeEnd(); |
| } |
| } |
| |
| public static class AnimalsAnnotation { |
| @JsonbTypeSerializer(AnimalListSerializer.class) |
| @JsonbTypeDeserializer(AnimalListDeserializer.class) |
| public List<Animal> animals = new ArrayList<>(); |
| } |
| |
| public static class Animals { |
| public List<Animal> animals = new ArrayList<>(); |
| } |
| |
| public static class AnimalDeserializer implements JsonbDeserializer<Animal> { |
| @Override |
| public Animal deserialize(final JsonParser jsonParser, |
| final DeserializationContext deserializationContext, |
| final Type type) { |
| Animal animal = null; |
| while (jsonParser.hasNext()) { |
| JsonParser.Event event = jsonParser.next(); |
| if (event == JsonParser.Event.START_OBJECT) { |
| continue; |
| } |
| if (event == JsonParser.Event.END_OBJECT) { |
| break; |
| } |
| if (event == JsonParser.Event.KEY_NAME) { |
| switch (jsonParser.getString()) { |
| case "type": |
| jsonParser.next(); |
| switch (jsonParser.getString()) { |
| case "cat": |
| animal = new Cat(); |
| break; |
| case "dog": |
| animal = new Dog(); |
| break; |
| default: |
| animal = new Animal(); |
| } |
| break; |
| case "name": |
| jsonParser.next(); |
| animal.name = jsonParser.getString(); |
| break; |
| case "age": |
| jsonParser.next(); |
| animal.age = jsonParser.getInt(); |
| break; |
| case "furry": |
| event = jsonParser.next(); |
| animal.furry = event == JsonParser.Event.VALUE_TRUE; |
| break; |
| case "weight": |
| jsonParser.next(); |
| animal.weight = jsonParser.getBigDecimal().floatValue(); |
| break; |
| case "cuddly": |
| event = jsonParser.next(); |
| ((Cat) animal).cuddly = event == JsonParser.Event.VALUE_TRUE; |
| break; |
| case "barking": |
| event = jsonParser.next(); |
| ((Dog) animal).barking = event == JsonParser.Event.VALUE_TRUE; |
| break; |
| default: |
| } |
| } |
| } |
| return animal; |
| } |
| } |
| |
| public static class AnimalSerializer implements JsonbSerializer<Animal> { |
| @Override |
| public void serialize(final Animal animal, final JsonGenerator jsonGenerator, |
| final SerializationContext serializationContext) { |
| if (animal != null) { |
| jsonGenerator.writeStartObject(); |
| if (Cat.class.isAssignableFrom(animal.getClass())) { |
| jsonGenerator.write("type", "cat"); |
| jsonGenerator.write("cuddly", ((Cat) animal).cuddly); |
| } else if (Dog.class.isAssignableFrom(animal.getClass())) { |
| jsonGenerator.write("type", "dog"); |
| jsonGenerator.write("barking", ((Dog) animal).barking); |
| } else { |
| jsonGenerator.write("type", "animal"); |
| } |
| jsonGenerator.write("age", animal.age); |
| jsonGenerator.write("furry", animal.furry); |
| jsonGenerator.write("name", animal.name); |
| jsonGenerator.write("weight", animal.weight); |
| jsonGenerator.writeEnd(); |
| } else { |
| serializationContext.serialize(null, jsonGenerator); |
| } |
| } |
| } |
| |
| public static class NameHolder { |
| @JsonbTypeSerializer(FooPassthroughSerializer.class) |
| public Named name; |
| } |
| |
| public static class Named { |
| public String name; |
| |
| @JsonbTypeSerializer(DetailNameSerializer.class) |
| public DetailName detailName; |
| } |
| |
| public static class DetailName { |
| public String name; |
| } |
| |
| public static class DetailNameSerializer implements JsonbSerializer<DetailName> { |
| @Override |
| public void serialize(final DetailName foo, final JsonGenerator jsonGenerator, |
| final SerializationContext serializationContext) { |
| serializationContext.serialize(foo, jsonGenerator); |
| jsonGenerator.write("detail", true); |
| } |
| } |
| |
| public static class FooPassthroughSerializer implements JsonbSerializer<Named> { |
| @Override |
| public void serialize(final Named foo, final JsonGenerator jsonGenerator, |
| final SerializationContext serializationContext) { |
| serializationContext.serialize(foo, jsonGenerator); |
| } |
| } |
| |
| public static class StringHolder implements Holder<String> { |
| private String instance = "Test"; |
| |
| public String getInstance() { |
| return instance; |
| } |
| |
| public void setInstance(final String instance) { |
| this.instance = instance; |
| } |
| } |
| |
| public static class SimpleContainerDeserializer implements JsonbDeserializer<StringHolder> { |
| @Override |
| public StringHolder deserialize(final JsonParser parser, final DeserializationContext ctx, final Type type) { |
| final StringHolder container = new StringHolder(); |
| |
| while (parser.hasNext()) { |
| final JsonParser.Event event = parser.next(); |
| if (event == JsonParser.Event.START_OBJECT) { |
| continue; |
| } |
| if (event == JsonParser.Event.END_OBJECT) { |
| break; |
| } |
| if (event == JsonParser.Event.KEY_NAME && "instance".equals(parser.getString())) { |
| container.setInstance(ctx.deserialize(String.class, parser) + " Deserialized"); |
| } |
| } |
| |
| return container; |
| } |
| } |
| |
| public static class SimpleContainerSerializer implements JsonbSerializer<StringHolder> { |
| @Override |
| public void serialize(final StringHolder container, final JsonGenerator generator, |
| final SerializationContext ctx) { |
| generator.writeStartObject(); |
| ctx.serialize("instance", container.getInstance() + " Serialized", generator); |
| generator.writeEnd(); |
| } |
| } |
| |
| public static class HolderHolder implements Holder<StringHolder> { |
| @JsonbTypeSerializer(SimpleContainerSerializer.class) |
| @JsonbTypeDeserializer(SimpleContainerDeserializer.class) |
| private StringHolder instance; |
| |
| @Override |
| public StringHolder getInstance() { |
| return instance; |
| } |
| |
| @Override |
| public void setInstance(StringHolder instance) { |
| this.instance = instance; |
| } |
| } |
| |
| public static class ArrayHolder implements Holder<StringHolder[]> { |
| @JsonbTypeSerializer(StringArraySerializer.class) |
| @JsonbTypeDeserializer(StringArrayDeserializer.class) |
| private StringHolder[] instance; |
| |
| @Override |
| public StringHolder[] getInstance() { |
| return instance; |
| } |
| |
| @Override |
| public void setInstance(final StringHolder[] instance) { |
| this.instance = instance; |
| } |
| } |
| |
| public static class StringArraySerializer implements JsonbSerializer<StringHolder[]> { |
| @Override |
| public void serialize(final StringHolder[] containers, |
| final JsonGenerator jsonGenerator, |
| final SerializationContext serializationContext) { |
| jsonGenerator.writeStartArray(); |
| for (final StringHolder container : containers) { |
| serializationContext.serialize(container, jsonGenerator); |
| } |
| jsonGenerator.writeEnd(); |
| } |
| } |
| |
| public static class StringArrayDeserializer implements JsonbDeserializer<StringHolder[]> { |
| @Override |
| public StringHolder[] deserialize(final JsonParser jsonParser, |
| final DeserializationContext deserializationContext, |
| final Type type) { |
| final List<StringHolder> containers = new LinkedList<>(); |
| |
| while (jsonParser.hasNext()) { |
| JsonParser.Event event = jsonParser.next(); |
| if (event == JsonParser.Event.START_OBJECT) { |
| containers.add(deserializationContext.deserialize( |
| new StringHolder() {}.getClass().getGenericSuperclass(), jsonParser)); |
| } |
| if (event == JsonParser.Event.END_OBJECT) { |
| break; |
| } |
| } |
| |
| return containers.toArray(new StringHolder[0]); |
| } |
| } |
| |
| public static class Foo { |
| public String name; |
| public int value; |
| public boolean flag; |
| } |
| |
| public static class MyWrapper { |
| @JsonbTransient |
| public Map<String, String> map; |
| |
| @JsonbTypeSerializer(MyMapSerializer.class) |
| public MyWrapper myWrapper; |
| } |
| |
| public static class MyMapSerializer implements JsonbSerializer<MyWrapper> { |
| @Override |
| public void serialize(final MyWrapper obj, final JsonGenerator generator, final SerializationContext ctx) { |
| ctx.serialize(obj, generator); |
| if (obj.map != null) { |
| obj.map.forEach((k, v) -> ctx.serialize(k, v, generator)); |
| } |
| } |
| } |
| |
| public static class UUIDSerializer implements JsonbSerializer<UUID> { |
| @Override |
| public void serialize(final UUID obj, final JsonGenerator generator, final SerializationContext ctx) { |
| generator.write(obj.toString()); |
| } |
| } |
| |
| public static class UUIDWrapper { |
| @JsonbTypeSerializer(UUIDSerializer.class) |
| public UUID uuid; |
| } |
| |
| public static class Wrapper { |
| |
| @JsonbTypeSerializer(FooSer.class) |
| @JsonbTypeDeserializer(FooDeser.class) |
| public Foo foo; |
| |
| @JsonbTypeSerializer(FooSer.class) |
| @JsonbTypeDeserializer(FooDeser.class) |
| public List<Foo> moreFoos = new ArrayList<>(); |
| } |
| |
| public static class IntList { |
| public List<Integer> elems = new ArrayList<>(); |
| } |
| |
| public enum MyStatus { |
| OK, WRONG; |
| } |
| |
| public static class EnumList { |
| public List<MyStatus> elems = new ArrayList<>(); |
| } |
| |
| public static class FooDeser implements JsonbDeserializer<Foo> { |
| @Override |
| public Foo deserialize(final JsonParser parser, final DeserializationContext ctx, final Type rtType) { |
| final Foo f = new Foo(); |
| assertTrue(parser.hasNext()); |
| assertEquals(JsonParser.Event.START_OBJECT, parser.next()); |
| assertTrue(parser.hasNext()); |
| assertEquals(JsonParser.Event.KEY_NAME, parser.next()); |
| assertEquals("full", parser.getString()); |
| assertTrue(parser.hasNext()); |
| assertEquals(JsonParser.Event.VALUE_TRUE, parser.next()); |
| assertTrue(parser.hasNext()); |
| assertEquals(JsonParser.Event.KEY_NAME, parser.next()); |
| assertEquals("name", parser.getString()); |
| assertTrue(parser.hasNext()); |
| assertEquals(JsonParser.Event.VALUE_STRING, parser.next()); |
| f.name = parser.getString(); |
| assertTrue(parser.hasNext()); |
| assertEquals(JsonParser.Event.END_OBJECT, parser.next()); |
| |
| // to be sure we passed there |
| f.flag = true; |
| f.value = f.name.length(); |
| return f; |
| } |
| } |
| |
| public static class FooSer implements JsonbSerializer<Foo> { |
| @Override |
| public void serialize(final Foo obj, final JsonGenerator generator, final SerializationContext ctx) { |
| generator.write("full", true); |
| generator.write("name", obj.name); |
| } |
| } |
| |
| /** |
| * see JOHNZON-169 |
| */ |
| @Test |
| public void testArrayParseWithDeserializer() { |
| String json = "{\"student\":[{\"val\":\"max,24\"}]}"; |
| Jsonb jsonb = JsonbBuilder.create(); |
| |
| StudentHolder studentHolder = jsonb.fromJson(json, StudentHolder.class); |
| assertNotNull(studentHolder); |
| assertNotNull(studentHolder.getStudent()); |
| assertEquals(1, studentHolder.getStudent().size()); |
| assertEquals("max", studentHolder.getStudent().get(0).getName()); |
| assertEquals(24, studentHolder.getStudent().get(0).getAge()); |
| } |
| |
| public static class Student { |
| private String name; |
| private int age; |
| |
| public String getName() { |
| return name; |
| } |
| |
| public void setName(String name) { |
| this.name = name; |
| } |
| |
| public int getAge() { |
| return age; |
| } |
| |
| public void setAge(int age) { |
| this.age = age; |
| } |
| } |
| |
| public static class StudentDeserializer implements JsonbDeserializer<Student> { |
| @Override |
| public Student deserialize(JsonParser parser, DeserializationContext ctx, Type rtType) { |
| String val = parser.getObject().getString("val"); |
| String[] parts = val.split(","); |
| Student s = new Student(); |
| s.setName(parts[0]); |
| s.setAge(Integer.parseInt(parts[1])); |
| |
| return s; |
| } |
| } |
| |
| public static class StudentHolder { |
| @JsonbTypeDeserializer(StudentDeserializer.class) |
| private List<Student> student; |
| |
| public List<Student> getStudent() { |
| return student; |
| } |
| |
| public void setStudent(List<Student> student) { |
| this.student = student; |
| } |
| } |
| |
| @JsonbTypeSerializer(OuterTestSerializer.class) |
| public static class OuterTestModel { |
| } |
| |
| @JsonbTypeSerializer(InnerTestSerializer.class) |
| public static class InnerTestModel { |
| } |
| |
| public static class OuterTestSerializer implements JsonbSerializer<OuterTestModel> { |
| @Override |
| public void serialize(final OuterTestModel obj, final JsonGenerator generator, final SerializationContext ctx) { |
| generator.writeStartObject(); |
| generator.write("foo", "generated in outer serializer"); |
| ctx.serialize("inner", new InnerTestModel(), generator); |
| generator.writeEnd(); |
| } |
| } |
| |
| public static class InnerTestSerializer implements JsonbSerializer<InnerTestModel> { |
| @Override |
| public void serialize(final InnerTestModel obj, final JsonGenerator generator, final SerializationContext ctx) { |
| generator.writeStartObject(); |
| generator.write("bar", "generated in inner serializer"); |
| generator.writeEnd(); |
| } |
| } |
| } |