Search in sources :

Example 1 with PropertyBasedObjectIdGenerator

use of com.fasterxml.jackson.databind.ser.impl.PropertyBasedObjectIdGenerator in project jackson-databind by FasterXML.

the class BeanSerializerFactory method constructObjectIdHandler.

protected ObjectIdWriter constructObjectIdHandler(SerializerProvider prov, BeanDescription beanDesc, List<BeanPropertyWriter> props) throws JsonMappingException {
    ObjectIdInfo objectIdInfo = beanDesc.getObjectIdInfo();
    if (objectIdInfo == null) {
        return null;
    }
    ObjectIdGenerator<?> gen;
    Class<?> implClass = objectIdInfo.getGeneratorType();
    // Just one special case: Property-based generator is trickier
    if (implClass == ObjectIdGenerators.PropertyGenerator.class) {
        // most special one, needs extra work
        String propName = objectIdInfo.getPropertyName().getSimpleName();
        BeanPropertyWriter idProp = null;
        for (int i = 0, len = props.size(); ; ++i) {
            if (i == len) {
                throw new IllegalArgumentException("Invalid Object Id definition for " + beanDesc.getBeanClass().getName() + ": can not find property with name '" + propName + "'");
            }
            BeanPropertyWriter prop = props.get(i);
            if (propName.equals(prop.getName())) {
                idProp = prop;
                /* Let's force it to be the first property to output
                     * (although it may still get rearranged etc)
                     */
                if (i > 0) {
                    props.remove(i);
                    props.add(0, idProp);
                }
                break;
            }
        }
        JavaType idType = idProp.getType();
        gen = new PropertyBasedObjectIdGenerator(objectIdInfo, idProp);
        // one more thing: must ensure that ObjectIdWriter does not actually write the value:
        return ObjectIdWriter.construct(idType, (PropertyName) null, gen, objectIdInfo.getAlwaysAsId());
    }
    // other types are simpler
    JavaType type = prov.constructType(implClass);
    // Could require type to be passed explicitly, but we should be able to find it too:
    JavaType idType = prov.getTypeFactory().findTypeParameters(type, ObjectIdGenerator.class)[0];
    gen = prov.objectIdGeneratorInstance(beanDesc.getClassInfo(), objectIdInfo);
    return ObjectIdWriter.construct(idType, objectIdInfo.getPropertyName(), gen, objectIdInfo.getAlwaysAsId());
}
Also used : PropertyBasedObjectIdGenerator(com.fasterxml.jackson.databind.ser.impl.PropertyBasedObjectIdGenerator) ObjectIdGenerator(com.fasterxml.jackson.annotation.ObjectIdGenerator) PropertyBasedObjectIdGenerator(com.fasterxml.jackson.databind.ser.impl.PropertyBasedObjectIdGenerator) ObjectIdGenerators(com.fasterxml.jackson.annotation.ObjectIdGenerators) FilteredBeanPropertyWriter(com.fasterxml.jackson.databind.ser.impl.FilteredBeanPropertyWriter)

Example 2 with PropertyBasedObjectIdGenerator

use of com.fasterxml.jackson.databind.ser.impl.PropertyBasedObjectIdGenerator in project jackson-databind by FasterXML.

the class BeanSerializerBase method createContextual.

@SuppressWarnings("incomplete-switch")
@Override
public JsonSerializer<?> createContextual(SerializerProvider provider, BeanProperty property) throws JsonMappingException {
    final AnnotationIntrospector intr = provider.getAnnotationIntrospector();
    final AnnotatedMember accessor = (property == null || intr == null) ? null : property.getMember();
    final SerializationConfig config = provider.getConfig();
    // Let's start with one big transmutation: Enums that are annotated
    // to serialize as Objects may want to revert
    JsonFormat.Value format = findFormatOverrides(provider, property, handledType());
    JsonFormat.Shape shape = null;
    if ((format != null) && format.hasShape()) {
        shape = format.getShape();
        // or, alternatively, asked to revert "back to" other representations...
        if ((shape != JsonFormat.Shape.ANY) && (shape != _serializationShape)) {
            if (_handledType.isEnum()) {
                switch(shape) {
                    case STRING:
                    case NUMBER:
                    case NUMBER_INT:
                        // 12-Oct-2014, tatu: May need to introspect full annotations... but
                        //   for now, just do class ones
                        BeanDescription desc = config.introspectClassAnnotations(_beanType);
                        JsonSerializer<?> ser = EnumSerializer.construct(_beanType.getRawClass(), provider.getConfig(), desc, format);
                        return provider.handlePrimaryContextualization(ser, property);
                }
            // 16-Oct-2016, tatu: Ditto for `Map`, `Map.Entry` subtypes
            } else if (shape == JsonFormat.Shape.NATURAL) {
                if (_beanType.isMapLikeType() && Map.class.isAssignableFrom(_handledType)) {
                    ;
                } else if (Map.Entry.class.isAssignableFrom(_handledType)) {
                    JavaType mapEntryType = _beanType.findSuperType(Map.Entry.class);
                    JavaType kt = mapEntryType.containedTypeOrUnknown(0);
                    JavaType vt = mapEntryType.containedTypeOrUnknown(1);
                    // 16-Oct-2016, tatu: could have problems with type handling, as we do not
                    //   see if "static" typing is needed, nor look for `TypeSerializer` yet...
                    JsonSerializer<?> ser = new MapEntrySerializer(_beanType, kt, vt, false, null, property);
                    return provider.handlePrimaryContextualization(ser, property);
                }
            }
        }
    }
    ObjectIdWriter oiw = _objectIdWriter;
    Set<String> ignoredProps = null;
    Object newFilterId = null;
    // Then we may have an override for Object Id
    if (accessor != null) {
        JsonIgnoreProperties.Value ignorals = intr.findPropertyIgnorals(accessor);
        if (ignorals != null) {
            ignoredProps = ignorals.findIgnoredForSerialization();
        }
        ObjectIdInfo objectIdInfo = intr.findObjectIdInfo(accessor);
        if (objectIdInfo == null) {
            // no ObjectId override, but maybe ObjectIdRef?
            if (oiw != null) {
                objectIdInfo = intr.findObjectReferenceInfo(accessor, new ObjectIdInfo(NAME_FOR_OBJECT_REF, null, null, null));
                oiw = _objectIdWriter.withAlwaysAsId(objectIdInfo.getAlwaysAsId());
            }
        } else {
            /* Ugh: mostly copied from BeanSerializerBase: but can't easily
                 * change it to be able to move to SerializerProvider (where it
                 * really belongs)
                 */
            // 2.1: allow modifications by "id ref" annotations as well:
            objectIdInfo = intr.findObjectReferenceInfo(accessor, objectIdInfo);
            ObjectIdGenerator<?> gen;
            Class<?> implClass = objectIdInfo.getGeneratorType();
            JavaType type = provider.constructType(implClass);
            JavaType idType = provider.getTypeFactory().findTypeParameters(type, ObjectIdGenerator.class)[0];
            // Property-based generator is trickier
            if (implClass == ObjectIdGenerators.PropertyGenerator.class) {
                // most special one, needs extra work
                String propName = objectIdInfo.getPropertyName().getSimpleName();
                BeanPropertyWriter idProp = null;
                for (int i = 0, len = _props.length; ; ++i) {
                    if (i == len) {
                        throw new IllegalArgumentException("Invalid Object Id definition for " + _handledType.getName() + ": can not find property with name '" + propName + "'");
                    }
                    BeanPropertyWriter prop = _props[i];
                    if (propName.equals(prop.getName())) {
                        idProp = prop;
                        /* Let's force it to be the first property to output
                             * (although it may still get rearranged etc)
                             */
                        if (i > 0) {
                            // note: must shuffle both regular properties and filtered
                            System.arraycopy(_props, 0, _props, 1, i);
                            _props[0] = idProp;
                            if (_filteredProps != null) {
                                BeanPropertyWriter fp = _filteredProps[i];
                                System.arraycopy(_filteredProps, 0, _filteredProps, 1, i);
                                _filteredProps[0] = fp;
                            }
                        }
                        break;
                    }
                }
                idType = idProp.getType();
                gen = new PropertyBasedObjectIdGenerator(objectIdInfo, idProp);
                oiw = ObjectIdWriter.construct(idType, (PropertyName) null, gen, objectIdInfo.getAlwaysAsId());
            } else {
                // other types need to be simpler
                gen = provider.objectIdGeneratorInstance(accessor, objectIdInfo);
                oiw = ObjectIdWriter.construct(idType, objectIdInfo.getPropertyName(), gen, objectIdInfo.getAlwaysAsId());
            }
        }
        // Or change Filter Id in use?
        Object filterId = intr.findFilterId(accessor);
        if (filterId != null) {
            // but only consider case of adding a new filter id (no removal via annotation)
            if (_propertyFilterId == null || !filterId.equals(_propertyFilterId)) {
                newFilterId = filterId;
            }
        }
    }
    // either way, need to resolve serializer:
    BeanSerializerBase contextual = this;
    if (oiw != null) {
        JsonSerializer<?> ser = provider.findValueSerializer(oiw.idType, property);
        oiw = oiw.withSerializer(ser);
        if (oiw != _objectIdWriter) {
            contextual = contextual.withObjectIdWriter(oiw);
        }
    }
    // And possibly add more properties to ignore
    if ((ignoredProps != null) && !ignoredProps.isEmpty()) {
        contextual = contextual.withIgnorals(ignoredProps);
    }
    if (newFilterId != null) {
        contextual = contextual.withFilterId(newFilterId);
    }
    if (shape == null) {
        shape = _serializationShape;
    }
    // last but not least; may need to transmute into as-array serialization
    if (shape == JsonFormat.Shape.ARRAY) {
        return contextual.asArraySerializer();
    }
    return contextual;
}
Also used : PropertyBasedObjectIdGenerator(com.fasterxml.jackson.databind.ser.impl.PropertyBasedObjectIdGenerator) AnnotatedMember(com.fasterxml.jackson.databind.introspect.AnnotatedMember) ObjectIdInfo(com.fasterxml.jackson.databind.introspect.ObjectIdInfo) PropertyBasedObjectIdGenerator(com.fasterxml.jackson.databind.ser.impl.PropertyBasedObjectIdGenerator) ObjectIdWriter(com.fasterxml.jackson.databind.ser.impl.ObjectIdWriter) MapEntrySerializer(com.fasterxml.jackson.databind.ser.impl.MapEntrySerializer)

Aggregations

PropertyBasedObjectIdGenerator (com.fasterxml.jackson.databind.ser.impl.PropertyBasedObjectIdGenerator)2 ObjectIdGenerator (com.fasterxml.jackson.annotation.ObjectIdGenerator)1 ObjectIdGenerators (com.fasterxml.jackson.annotation.ObjectIdGenerators)1 AnnotatedMember (com.fasterxml.jackson.databind.introspect.AnnotatedMember)1 ObjectIdInfo (com.fasterxml.jackson.databind.introspect.ObjectIdInfo)1 FilteredBeanPropertyWriter (com.fasterxml.jackson.databind.ser.impl.FilteredBeanPropertyWriter)1 MapEntrySerializer (com.fasterxml.jackson.databind.ser.impl.MapEntrySerializer)1 ObjectIdWriter (com.fasterxml.jackson.databind.ser.impl.ObjectIdWriter)1