@Override @SuppressWarnings("unchecked") public T deserialize(JsonParser parser, DeserializationContext context, Type rtType) { Unmarshaller unmarshaller = (Unmarshaller) context; unmarshaller.setCurrent(this); try { unmarshaller.getJsonbContext().addProcessedType(adapterInfo.getBindingType()); final A result = adaptedTypeDeserializer.deserialize(parser, context, rtType); final T adapted = ((JsonbAdapter<T, A>) adapterInfo.getAdapter()).adaptFromJson(result); unmarshaller.setCurrent(wrapperItem); return adapted; } catch (Exception e) { throw new JsonbException(Messages.getMessage(MessageKeys.ADAPTER_EXCEPTION, adapterInfo.getBindingType(), adapterInfo.getToType(), adapterInfo.getAdapter().getClass()), e); } finally { unmarshaller.getJsonbContext().removeProcessedType(adapterInfo.getBindingType()); } }
/** * Called during context creation, introspecting user components provided with JsonbConfig. */ void init() { final JsonbSerializer<?>[] serializers = (JsonbSerializer<?>[])jsonbContext.getConfig().getProperty(JsonbConfig.SERIALIZERS).orElseGet(()->new JsonbSerializer<?>[]{}); for (JsonbSerializer serializer : serializers) { SerializerBinding serializerBinding = introspectSerializerBinding(serializer.getClass(), serializer); addSerializer(serializerBinding.getBindingType(), serializerBinding); } final JsonbDeserializer<?>[] deserializers = (JsonbDeserializer<?>[])jsonbContext.getConfig().getProperty(JsonbConfig.DESERIALIZERS).orElseGet(()->new JsonbDeserializer<?>[]{}); for (JsonbDeserializer deserializer : deserializers) { DeserializerBinding deserializerBinding = introspectDeserializerBinding(deserializer.getClass(), deserializer); addDeserializer(deserializerBinding.getBindingType(), deserializerBinding); } final JsonbAdapter<?, ?>[] adapters = (JsonbAdapter<?, ?>[]) jsonbContext.getConfig().getProperty(JsonbConfig.ADAPTERS).orElseGet(()->new JsonbAdapter<?, ?>[]{}); for (JsonbAdapter<?, ?> adapter : adapters) { AdapterBinding adapterBinding = introspectAdapterBinding(adapter.getClass(), adapter); addAdapter(adapterBinding.getBindingType(), adapterBinding); } }
@Test public void testValueFieldAdapter() throws Exception { JsonbAdapter<?, ?>[] adapters = { new JsonbAdapter<Integer, String>() { @Override public String adaptToJson(Integer integer) { return String.valueOf(integer); } @Override public Integer adaptFromJson(String s) { return Integer.parseInt(s); } } }; jsonb = JsonbBuilder.create(new JsonbConfig().setProperty(JsonbConfig.ADAPTERS, adapters)); AdaptedPojo pojo = new AdaptedPojo(); pojo.intField = 11; String json = jsonb.toJson(pojo); assertEquals("{\"intField\":\"11\"}", json); AdaptedPojo<?> result = jsonb.fromJson("{\"intField\":\"10\"}", AdaptedPojo.class); assertEquals(Integer.valueOf(10), result.intField); }
@Test public void testStringToGenericCollectionAdapter() throws Exception { JsonbAdapter<?, ?>[] adapters = {new IntegerListToStringAdapter()}; jsonb = JsonbBuilder.create(new JsonbConfig().setProperty(JsonbConfig.ADAPTERS, adapters)); AdaptedPojo<List<Integer>> pojo = new AdaptedPojo<>(); pojo.tVar = Arrays.asList(11, 22, 33); pojo.integerList = Arrays.asList(110, 111, 101); String marshalledJson = jsonb.toJson(pojo, new TestTypeToken<AdaptedPojo<List<Integer>>>(){}.getType()); assertEquals("{\"integerList\":\"110#111#101\"," + "\"tVar\":\"11#22#33\"}", marshalledJson); String toUnmarshall = "{\"integerList\":\"11#22#33#44\",\"stringList\":[\"first\",\"second\"]," + "\"tVar\":\"110#111#101\"}"; AdaptedPojo result = jsonb.fromJson(toUnmarshall, new TestTypeToken<AdaptedPojo<List<Integer>>>(){}.getType()); List<Integer> expectedIntegerList = Arrays.asList(11, 22, 33, 44); List<String> expectedStringList = Arrays.asList("first", "second"); List<Integer> expectedTList = Arrays.asList(110, 111, 101); assertEquals(expectedIntegerList, result.integerList); assertEquals(expectedStringList, result.stringList); assertEquals(expectedTList, result.tVar); }
@Test public void testAdaptObjectInCollection() throws Exception { JsonbAdapter<?, ?>[] adapters = {new BoxToCrateCompatibleGenericsAdapter<Integer>() { }}; jsonb = JsonbBuilder.create(new JsonbConfig().setProperty(JsonbConfig.ADAPTERS, adapters)); AdaptedPojo<Integer> pojo = new AdaptedPojo<>(); pojo.tGenericBoxList = new ArrayList<>(); pojo.tGenericBoxList.add(new GenericBox<>("GEN_BOX_STR_1", 110)); pojo.tGenericBoxList.add(new GenericBox<>("GEN_BOX_STR_2", 101)); String marshalledJson = jsonb.toJson(pojo, new TestTypeToken<AdaptedPojo<Integer>>(){}.getType()); assertEquals("{\"tGenericBoxList\":[{\"adaptedT\":110,\"crateStrField\":\"GEN_BOX_STR_1\"},{\"adaptedT\":101,\"crateStrField\":\"GEN_BOX_STR_2\"}]}", marshalledJson); String toUnmarshall = "{\"integerList\":[11,22,33,44],\"stringList\":[\"first\",\"second\"]," + "\"tGenericBoxList\":[{\"crateStrField\":\"FirstCrate\",\"adaptedT\":11},{\"crateStrField\":\"SecondCrate\",\"adaptedT\":22}]}"; AdaptedPojo<Integer> result = jsonb.fromJson(toUnmarshall, new TestTypeToken<AdaptedPojo<Integer>>(){}.getType()); assertEquals("FirstCrate", result.tGenericBoxList.get(0).getStrField()); assertEquals("SecondCrate", result.tGenericBoxList.get(1).getStrField()); assertEquals(Integer.valueOf(11), result.tGenericBoxList.get(0).getX()); assertEquals(Integer.valueOf(22), result.tGenericBoxList.get(1).getX()); }
@Test public void testAdaptRoot() throws Exception { JsonbAdapter<?, ?>[] adapters = {new JsonbAdapter<Box, Crate>() { @Override public Crate adaptToJson(Box box) { return new Crate(box.getBoxStrField(), box.getBoxIntegerField()); } @Override public Box adaptFromJson(Crate crate) { return new Box(crate.getCrateStrField(), crate.getCrateIntField()); } }}; jsonb = JsonbBuilder.create(new JsonbConfig().setProperty(JsonbConfig.ADAPTERS, adapters)); Box pojo = new Box("BOX_STR", 101); String marshalledJson = jsonb.toJson(pojo); assertEquals("{\"crateIntField\":101,\"crateStrField\":\"BOX_STR\"}", marshalledJson); Box result = jsonb.fromJson("{\"crateIntField\":110,\"crateStrField\":\"CRATE_STR\"}", Box.class); assertEquals("CRATE_STR", result.getBoxStrField()); assertEquals(Integer.valueOf(110), result.getBoxIntegerField()); }
@Override @SuppressWarnings("unchecked") public void serialize(T obj, JsonGenerator generator, SerializationContext ctx) { JsonbContext jsonbContext = ((Marshaller) ctx).getJsonbContext(); try { jsonbContext.addProcessedType(adapterInfo.getBindingType()); final JsonbAdapter<T, A> adapter = (JsonbAdapter<T, A>) adapterInfo.getAdapter(); A adapted = adapter.adaptToJson(obj); final JsonbSerializer<A> serializer = resolveSerializer((Marshaller) ctx, adapted); serializer.serialize(adapted, generator, ctx); } catch (Exception e) { throw new JsonbException(Messages.getMessage(MessageKeys.ADAPTER_EXCEPTION, adapterInfo.getBindingType(), adapterInfo.getToType(), adapterInfo.getAdapter().getClass()), e); } finally { jsonbContext.removeProcessedType(adapterInfo.getBindingType()); } }
private AdapterBinding getAdapterBindingFromAnnotation(JsonbTypeAdapter adapterAnnotation, Optional<Class<?>> expectedClass) { final Class<? extends JsonbAdapter> adapterClass = adapterAnnotation.value(); final AdapterBinding adapterBinding = jsonbContext.getComponentMatcher().introspectAdapterBinding(adapterClass, null); if (expectedClass.isPresent() && !(ReflectionUtils.getRawType(adapterBinding.getBindingType()).equals(expectedClass.get()))) { throw new JsonbException(Messages.getMessage(MessageKeys.ADAPTER_INCOMPATIBLE, adapterBinding.getBindingType(), expectedClass.get())); } return adapterBinding; }
/** * Introspect components generic information and put resolved types into metadata wrapper. * * @param adapterClass class of an components * @param instance components instance * @return introspected info with resolved typevar types. */ AdapterBinding introspectAdapterBinding(Class<? extends JsonbAdapter> adapterClass, JsonbAdapter instance) { final ParameterizedType adapterRuntimeType = ReflectionUtils.findParameterizedType(adapterClass, JsonbAdapter.class); final Type[] adapterTypeArguments = adapterRuntimeType.getActualTypeArguments(); Type adaptFromType = resolveTypeArg(adapterTypeArguments[0], adapterClass); Type adaptToType = resolveTypeArg(adapterTypeArguments[1], adapterClass); final ComponentBindings componentBindings = getBindingInfo(adaptFromType); if (componentBindings.getAdapterInfo() != null && componentBindings.getAdapterInfo().getAdapter().getClass().equals(adapterClass)) { return componentBindings.getAdapterInfo(); } JsonbAdapter newAdapter = instance != null ? instance : jsonbContext.getComponentInstanceCreator().getOrCreateComponent(adapterClass); return new AdapterBinding(adaptFromType, adaptToType, newAdapter); }
/** * Adapter info with type to "adapt from", type to "adapt to" and an components itself. * @param fromType from not null * @param toType to not null * @param adapter components not null */ public AdapterBinding(Type fromType, Type toType, JsonbAdapter<?, ?> adapter) { super(fromType); Objects.requireNonNull(toType); Objects.requireNonNull(adapter); this.toType = toType; this.adapter = adapter; }
@Test public void testGenericAdapter() throws Exception { JsonbAdapter<?, ?>[] adapters = {new BoxToCrateCompatibleGenericsAdapter<Integer>() { }}; jsonb = JsonbBuilder.create(new JsonbConfig().setProperty(JsonbConfig.ADAPTERS, adapters)); AdaptedPojo<Integer> pojo = new AdaptedPojo<>(); pojo.strField = "POJO_STRING"; pojo.intBox = new GenericBox<>("INT_BOX_STR", 11); pojo.tBox = new GenericBox<>("T_BOX_STR", 110); String marshalledJson = jsonb.toJson(pojo, new TestTypeToken<AdaptedPojo<Integer>>(){}.getType()); assertEquals("{\"intBox\":{\"adaptedT\":11,\"crateStrField\":\"INT_BOX_STR\"}," + "\"strField\":\"POJO_STRING\"," + "\"tBox\":{\"adaptedT\":110,\"crateStrField\":\"T_BOX_STR\"}}", marshalledJson); String toUnmarshall = "{\"intBox\":{\"crateStrField\":\"Box3\",\"adaptedT\":33}," + "\"tBox\":{\"crateStrField\":\"tGenBoxCrateStr\",\"adaptedT\":22}," + "\"strField\":\"POJO_STRING\"," + "\"strBox\":{\"strField\":\"strBoxStr\",\"x\":\"44\"}}"; AdaptedPojo result = jsonb.fromJson(toUnmarshall, new TestTypeToken<AdaptedPojo<Integer>>(){}.getType()); assertEquals("POJO_STRING", result.strField); assertEquals("Box3", result.intBox.getStrField()); assertEquals(33, result.intBox.getX()); assertEquals("tGenBoxCrateStr", result.tBox.getStrField()); assertEquals(22, result.tBox.getX()); assertEquals("strBoxStr", result.strBox.getStrField()); assertEquals("44", result.strBox.getX()); }
@Test public void testPropagatedTypeArgs() throws Exception { JsonbAdapter<?, ?>[] adapters = {new BoxToCratePropagatedIntegerStringAdapter()}; jsonb = JsonbBuilder.create(new JsonbConfig().setProperty(JsonbConfig.ADAPTERS, adapters)); AdaptedPojo<Integer> pojo = new AdaptedPojo<>(); pojo.intBox = new GenericBox<>("INT_BOX_STR", 110); pojo.tBox = new GenericBox<>("T_BOX_STR", 111); pojo.strBox = new GenericBox<>("STR_BOX_STR", "101"); String marshalledJson = jsonb.toJson(pojo, new TestTypeToken<AdaptedPojo<Integer>>(){}.getType()); assertEquals("{\"intBox\":{\"adaptedT\":{\"x\":[\"110\"]},\"crateStrField\":\"INT_BOX_STR\"}," + "\"strBox\":{\"strField\":\"STR_BOX_STR\",\"x\":\"101\"}," + "\"tBox\":{\"adaptedT\":{\"x\":[\"111\"]},\"crateStrField\":\"T_BOX_STR\"}}", marshalledJson); String toUnmarshall = "{\"intBox\":{\"crateStrField\":\"strCrateStr\",\"adaptedT\":{\"strField\":\"crateBoxStrField\",\"x\":[\"77\"]}}," + "\"tBox\":{\"crateStrField\":\"tStrCrateStr\",\"adaptedT\":{\"strField\":\"crateBoxStrField\",\"x\":[\"88\"]}}," + "\"strField\":\"POJO_STRING\"," + "\"strBox\":{\"strField\":\"strBoxStr\",\"x\":\"44\"}}"; AdaptedPojo result = jsonb.fromJson(toUnmarshall, new TestTypeToken<AdaptedPojo<Integer>>(){}.getType()); assertEquals("POJO_STRING", result.strField); assertEquals("strCrateStr", result.intBox.getStrField()); assertEquals(77, result.intBox.getX()); assertEquals("tStrCrateStr", result.tBox.getStrField()); assertEquals(88, result.tBox.getX()); assertEquals("strBoxStr", result.strBox.getStrField()); assertEquals("44", result.strBox.getX()); }
@Test public void testAdaptTypeIntoCollection() throws Exception { JsonbAdapter<?, ?>[] adapters = {new JsonbAdapter<String, List<Integer>>() { @Override public List<Integer> adaptToJson(String s) { List<Integer> result = new ArrayList<>(); for (String str : s.split(",")) { result.add(Integer.parseInt(str)); } return result; } @Override public String adaptFromJson(List<Integer> ints) { StringBuilder sb = new StringBuilder(); for (Integer i : ints) { if (!sb.toString().isEmpty()) { sb.append(","); } sb.append(i); } return sb.toString(); } } }; jsonb = JsonbBuilder.create(new JsonbConfig().setProperty(JsonbConfig.ADAPTERS, adapters)); String json = "{\"strValues\":[11,22,33]}"; final NonGenericPojo object = new NonGenericPojo(); object.strValues = "11,22,33"; assertEquals(json, jsonb.toJson(object)); NonGenericPojo pojo = jsonb.fromJson(json, NonGenericPojo.class); assertEquals("11,22,33", pojo.strValues); }
@Test public void testMarshallGenericField() throws Exception { JsonbAdapter<?, ?>[] adapters = {new BoxToCratePropagatedIntegerStringAdapter()}; jsonb = JsonbBuilder.create(new JsonbConfig().setProperty(JsonbConfig.ADAPTERS, adapters)); AdaptedPojo<Integer> adaptedPojo = new AdaptedPojo<>(); adaptedPojo.tBox = new GenericBox<>("tGenBoxStrField", 22); adaptedPojo.intBox = new GenericBox<>("genBoxStrField", 11); String json = jsonb.toJson(adaptedPojo, new TestTypeToken<AdaptedPojo<Integer>>(){}.getType()); assertEquals("{\"intBox\":{\"adaptedT\":{\"x\":[\"11\"]},\"crateStrField\":\"genBoxStrField\"},\"tBox\":{\"adaptedT\":{\"x\":[\"22\"]},\"crateStrField\":\"tGenBoxStrField\"}}", json); AdaptedPojo<Integer> unmarshalledAdaptedPojo = jsonb.fromJson(json, new TestTypeToken<AdaptedPojo<Integer>>(){}.getType()); assertEquals("genBoxStrField", unmarshalledAdaptedPojo.intBox.getStrField()); assertEquals(Integer.valueOf(11), unmarshalledAdaptedPojo.intBox.getX()); }
@Test public void testTypeVariable() throws Exception { JsonbAdapter<?, ?>[] adapters = {new JsonbAdapter<List<GenericBox<Double>>, BigDecimal>() { @Override public BigDecimal adaptToJson(List<GenericBox<Double>> genericBoxes) { return BigDecimal.valueOf(genericBoxes.get(0).getX()); } @Override public List<GenericBox<Double>> adaptFromJson(BigDecimal bigDecimal) { List<GenericBox<Double>> list = new ArrayList<>(); list.add(new GenericBox<>("", bigDecimal.doubleValue())); return list; } }}; jsonb = JsonbBuilder.create(new JsonbConfig().setProperty(JsonbConfig.ADAPTERS, adapters)); AdaptedPojo<List<GenericBox<Double>>> intBoxPojo = new AdaptedPojo<>(); List<GenericBox<Double>> intBoxList = new ArrayList<>(); intBoxList.add(new GenericBox<>("", 11d)); intBoxPojo.tVar = intBoxList; String json = jsonb.toJson(intBoxPojo, new TestTypeToken<AdaptedPojo<List<GenericBox<Double>>>>(){}.getType()); assertEquals("{\"tVar\":11.0}", json); AdaptedPojo<List<GenericBox<Double>>> result = jsonb.fromJson(json, new TestTypeToken<AdaptedPojo<List<GenericBox<Double>>>>(){}.getType()); assertEquals(Double.valueOf(11), result.tVar.get(0).getX()); }
private Adapter<?, ?> toConverter(final Type type, final JsonbTypeAdapter adapter, final JsonbDateFormat dateFormat, final JsonbNumberFormat numberFormat) throws InstantiationException, IllegalAccessException { final Adapter converter; if (adapter != null) { final Class<? extends JsonbAdapter> value = adapter.value(); final ParameterizedType pt = findPt(value, JsonbAdapter.class); if (pt == null) { throw new IllegalArgumentException(value + " doesn't implement JsonbAdapter"); } final JohnzonAdapterFactory.Instance<? extends JsonbAdapter> instance = newInstance(value); toRelease.add(instance); final Type[] actualTypeArguments = pt.getActualTypeArguments(); converter = new JohnzonJsonbAdapter(instance.getValue(), actualTypeArguments[0], actualTypeArguments[1]); } else if (dateFormat != null) { // TODO: support lists, LocalDate? if (Date.class == type) { converter = new ConverterAdapter<>(new JsonbDateConverter(dateFormat)); } else if (LocalDateTime.class == type) { converter = new ConverterAdapter<>(new JsonbLocalDateTimeConverter(dateFormat)); } else if (LocalDate.class == type) { converter = new ConverterAdapter<>(new JsonbLocalDateConverter(dateFormat)); } else if (ZonedDateTime.class == type) { converter = new ConverterAdapter<>(new JsonbZonedDateTimeConverter(dateFormat)); } else { throw new IllegalArgumentException(type + " not a supported date type"); } } else if (numberFormat != null) { // TODO: support lists? converter = new ConverterAdapter<>(new JsonbNumberConverter(numberFormat)); } else { converter = new ConverterAdapter<>(new JsonbValueConverter()); } return converter; }
public JohnzonJsonbAdapter(final JsonbAdapter<OriginalType, JsonType> delegate, final Type from, final Type to) { this.delegate = delegate; this.from = from; this.to = to; }
/** * Get actual components to adapt object value * @return components */ public JsonbAdapter<?, ?> getAdapter() { return adapter; }