/** * Try to cache serializer for this bean property. Only if type cannot be changed during runtime. * * @return serializer instance to be cached */ @SuppressWarnings("unchecked") private JsonbSerializer<?> resolveCachedSerializer() { if (!ReflectionUtils.isResolvedType(propertyType)) { return null; } if (customization.getAdapterBinding() != null) { return new AdaptedObjectSerializer<>(this, customization.getAdapterBinding()); } if (customization.getSerializerBinding() != null) { return new UserSerializerSerializer<>(this, customization.getSerializerBinding().getJsonbSerializer()); } final Class<?> propertyRawType = ReflectionUtils.getRawType(propertyType); final Optional<SerializerProviderWrapper> valueSerializerProvider = DefaultSerializers.getInstance().findValueSerializerProvider(propertyRawType); if (valueSerializerProvider.isPresent()) { return valueSerializerProvider.get().getSerializerProvider().provideSerializer(this); } return null; }
/** * Instance is not created in case of array items, because, we don't know how long it should be * till parser ends parsing. */ private JsonbSerializer<?> createArrayItem(Class<?> componentType) { if (componentType == byte.class) { return new ByteArraySerializer(this); } else if (componentType == short.class) { return new ShortArraySerializer(this); } else if (componentType == int.class) { return new IntArraySerializer(this); } else if (componentType == long.class) { return new LongArraySerializer(this); } else if (componentType == float.class) { return new FloatArraySerializer(this); } else if (componentType == double.class) { return new DoubleArraySerializer(this); } else { return new ObjectArraySerializer(this); } }
/** * 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); } }
/** * Serializes root element. * * @param <T> Root type * @param root Root. * @param generator JSON generator. * @param model Binding model. */ @SuppressWarnings("unchecked") public <T> void serializeRoot(T root, JsonGenerator generator, JsonBindingModel model) { final JsonbSerializer<T> rootSerializer = (JsonbSerializer<T>) getRootSerializer(root.getClass(), model); if (jsonbContext.getConfigProperties().isStrictIJson() && rootSerializer instanceof AbstractValueTypeSerializer) { throw new JsonbException(Messages.getMessage(MessageKeys.IJSON_ENABLED_SINGLE_VALUE)); } rootSerializer.serialize(root, generator, this); }
private JsonbSerializer<?> getRootSerializer(Class<?> rootClazz, JsonBindingModel model) { final ContainerSerializerProvider serializerProvider = getMappingContext().getSerializerProvider(rootClazz); if (serializerProvider != null) { return serializerProvider .provideSerializer(new JsonbPropertyInfo() .withRuntimeType(runtimeType) .withClassModel(getMappingContext(). getClassModel(rootClazz)) .withJsonBindingModel(model)); } return new SerializerBuilder(jsonbContext) .withObjectClass(rootClazz) .withType(model.getType()) .withModel(model).build(); }
/** * Return last used serializer if last value class matches. * @param valueClass class of the serialized object * @return cached serializer or null */ protected JsonbSerializer<?> getValueSerializer(Class<?> valueClass) { if (valueSerializer != null && valueClass == this.valueClass) { return valueSerializer; } return null; }
/** * Cache a serializer and serialized object class for next use. * @param valueSerializer serializer * @param valueClass class of serializer object */ protected void addValueSerializer(JsonbSerializer<?> valueSerializer, Class<?> valueClass) { Objects.requireNonNull(valueSerializer); Objects.requireNonNull(valueClass); this.valueSerializer = valueSerializer; this.valueClass = valueClass; }
protected void serializeItem(Object item, JsonGenerator generator, SerializationContext ctx, JsonBindingModel model) { if (item == null) { generator.writeNull(); return; } Class<?> itemClass = item.getClass(); JsonbSerializer<?> serializer = getValueSerializer(itemClass); if (serializer == null) { serializer = new SerializerBuilder(((Marshaller)ctx).getJsonbContext()).withObjectClass(itemClass).withWrapper(this).withModel(model).build(); addValueSerializer(serializer, itemClass); } serializerCaptor(serializer, item, generator, ctx); }
@SuppressWarnings("unchecked") private void marshallProperty(T object, JsonGenerator generator, SerializationContext ctx, PropertyModel propertyModel) { Marshaller marshaller = (Marshaller) ctx; if (propertyModel.isReadable()) { final Object propertyValue = propertyModel.getValue(object); if (propertyValue == null || isEmptyOptional(propertyValue)) { if (propertyModel.getCustomization().isNillable()) { generator.writeNull(propertyModel.getWriteName()); } return; } generator.writeKey(propertyModel.getWriteName()); final JsonbSerializer<?> propertyCachedSerializer = propertyModel.getPropertySerializer(); if (propertyCachedSerializer != null) { serializerCaptor(propertyCachedSerializer, propertyValue, generator, ctx); return; } Optional<Type> runtimeTypeOptional = ReflectionUtils.resolveOptionalType(this, propertyModel.getType()); Type genericType = runtimeTypeOptional.orElse(null); final JsonbSerializer<?> serializer = new SerializerBuilder(marshaller.getJsonbContext()) .withWrapper(this) .withObjectClass(propertyValue.getClass()).withModel(propertyModel) .withType(genericType).build(); serializerCaptor(serializer, propertyValue, generator, ctx); } }
@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()); } }
@SuppressWarnings("unchecked") private JsonbSerializer<A> resolveSerializer(Marshaller ctx, A adapted) { final ContainerSerializerProvider cached = ctx.getMappingContext().getSerializerProvider(adapted.getClass()); if (cached != null) { return (JsonbSerializer<A>) cached.provideSerializer(new JsonbPropertyInfo().withWrapper(this).withRuntimeType(model.getType()).withJsonBindingModel(model)); } return (JsonbSerializer<A>) new SerializerBuilder(ctx.getJsonbContext()).withObjectClass(adapted.getClass()).withModel(model).withWrapper(this).build(); }
@Override public void serialize(T obj, JsonGenerator generator, SerializationContext ctx) { JsonbContext jsonbContext = ((ProcessingContext) ctx).getJsonbContext(); if (obj == null || !obj.isPresent()) { if (!wrapperModel.getCustomization().isNillable()) { return; } generator.writeNull(); return; } Object optionalValue = obj.get(); final JsonbSerializer<?> serializer = new SerializerBuilder(jsonbContext).withObjectClass(optionalValue.getClass()) .withType(optionalValueType).withWrapper(wrapper).withModel(wrapperModel).build(); serialCaptor(serializer, optionalValue, generator, ctx); }
/** * Checks for {@link JsonbSerializer} on a property. * @param property property not null * @return components info */ public SerializerBinding getSerializerBinding(Property property) { Objects.requireNonNull(property); JsonbTypeSerializer serializerAnnotation = getAnnotationFromProperty(JsonbTypeSerializer.class, property) .orElseGet(()-> getAnnotationFromPropertyType(property, JsonbTypeSerializer.class)); if (serializerAnnotation == null) { return null; } final Class<? extends JsonbSerializer> serializerClass = serializerAnnotation.value(); return jsonbContext.getComponentMatcher().introspectSerializerBinding(serializerClass, null); }
/** * If an instance of serializerClass is present in context and is bound for same type, return that instance. * Otherwise create new instance and set it to context. * * @param serializerClass class of deserializer * @param instance instance to use if not cached * @return wrapper used in property models */ @SuppressWarnings("unchecked") SerializerBinding introspectSerializerBinding(Class<? extends JsonbSerializer> serializerClass, JsonbSerializer instance) { final ParameterizedType serializerRuntimeType = ReflectionUtils.findParameterizedType(serializerClass, JsonbSerializer.class); Type serBindingType = resolveTypeArg(serializerRuntimeType.getActualTypeArguments()[0], serializerClass.getClass()); final ComponentBindings componentBindings = getBindingInfo(serBindingType); if (componentBindings.getSerializer() != null && componentBindings.getSerializer().getClass().equals(serializerClass)) { return componentBindings.getSerializer(); } else { JsonbSerializer serializer = instance != null ? instance : jsonbContext.getComponentInstanceCreator() .getOrCreateComponent(serializerClass); return new SerializerBinding(serBindingType, serializer); } }
@SuppressWarnings("unchecked") protected <X> void serializerCaptor(JsonbSerializer<?> serializer, X object, JsonGenerator generator, SerializationContext ctx) { ((JsonbSerializer<X>) serializer).serialize(object, generator, ctx); }
@Override public JsonbSerializer<?> provideSerializer(JsonbPropertyInfo propertyInfo) { return new ObjectSerializer<>(propertyInfo.getWrapper(), propertyInfo.getRuntimeType(), propertyInfo.getClassModel(), propertyInfo.getJsonBindingModel()); }
/** * Builds a {@link JsonbSerializer}. * * @return JsonbSerializer. */ public JsonbSerializer<?> build() { runtimeType = resolveRuntimeType(); if (getModel() != null && (getModel().getCustomization() == null || getModel().getCustomization() instanceof ComponentBoundCustomization)) { ComponentBoundCustomization customization = (ComponentBoundCustomization) getModel().getCustomization(); //First check if user deserializer is registered for such type final ComponentMatcher componentMatcher = jsonbContext.getComponentMatcher(); Optional<SerializerBinding<?>> userSerializer = componentMatcher.getSerializerBinding(getRuntimeType(), customization); if (userSerializer.isPresent() && !jsonbContext.containsProcessedType(userSerializer.get().getBindingType())) { return new UserSerializerSerializer<>(model, userSerializer.get().getJsonbSerializer()); } //Second user components is registered. Optional<AdapterBinding> adapterInfoOptional = componentMatcher.getAdapterBinding(getRuntimeType(), customization); if (adapterInfoOptional.isPresent() && !jsonbContext.containsProcessedType(adapterInfoOptional.get().getBindingType())) { return new AdaptedObjectSerializer<>(getModel(), adapterInfoOptional.get()); } } final Optional<AbstractValueTypeSerializer<?>> supportedTypeSerializer = getSupportedTypeSerializer(objectClass); if (supportedTypeSerializer.isPresent()) { return supportedTypeSerializer.get(); } if (Collection.class.isAssignableFrom(objectClass)) { return new CollectionSerializer<>(this); } else if (Map.class.isAssignableFrom(objectClass)) { return new MapSerializer<>(this); } else if (isByteArray(objectClass)) { String strategy = jsonbContext.getConfigProperties().getBinaryDataStrategy(); switch (strategy) { case BinaryDataStrategy.BYTE: return new ByteArraySerializer(this); default: return new ByteArrayBase64Serializer(byte[].class, getModel()); } } else if (objectClass.isArray() || getRuntimeType() instanceof GenericArrayType) { return createArrayItem(objectClass.getComponentType()); } else if (JsonValue.class.isAssignableFrom(objectClass)) { if(JsonObject.class.isAssignableFrom(objectClass)) { return new JsonObjectSerializer(this); } else { return new JsonArraySerializer(this); } } else if (Optional.class.isAssignableFrom(objectClass)) { return new OptionalObjectSerializer<>(this); } else { jsonbContext.getMappingContext().addSerializerProvider(objectClass, new ObjectSerializerProvider()); return new ObjectSerializer<>(this); } }
@SuppressWarnings("unchecked") private <T> void serialCaptor(JsonbSerializer<?> serializer, T object, JsonGenerator generator, SerializationContext context) { ((JsonbSerializer<T>) serializer).serialize(object, generator, context); }
/** * Gets serializer. * * @return Serializer. */ public JsonbSerializer<?> getPropertySerializer() { return propertySerializer; }
/** * Provides container serializer instance for given property. * * @param propertyInfo Property to create serializer for. * @return Serializer instance. */ JsonbSerializer<?> provideSerializer(JsonbPropertyInfo propertyInfo);
/** * Create instance of current item with its builder. * * @param model model * @param userSerializer user serializer */ public UserSerializerSerializer(JsonBindingModel model, JsonbSerializer<T> userSerializer) { this.model = model; this.userSerializer = userSerializer; }
/** * Creates a new instance. * * @param bindingType Generic type argument of serializer. Not null. * @param jsonbSerializer Serializer. Can be null. */ public SerializerBinding(Type bindingType, JsonbSerializer<T> jsonbSerializer) { super(bindingType); this.jsonbSerializer = jsonbSerializer; }
/** * Returns a serializer if any. * * @return Serializer. */ public JsonbSerializer<T> getJsonbSerializer() { return jsonbSerializer; }