All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fasterxml.jackson.dataformat.csv.CsvMapper Maven / Gradle / Ivy

The newest version!
package com.fasterxml.jackson.dataformat.csv;

import org.codehaus.jackson.*;
import org.codehaus.jackson.map.*;
import org.codehaus.jackson.type.JavaType;
import org.codehaus.jackson.type.TypeReference;

import com.fasterxml.jackson.dataformat.csv.impl.LRUMap;

/**
 * Specialized {@link ObjectMapper}, with extended functionality to
 * produce {@link CsvSchema} instances out of POJOs.
 */
public class CsvMapper extends ObjectMapper
{
    /**
     * Simple caching for schema instances, given that they are relatively expensive
     * to construct; this one is for "loose" (non-typed) schemas
     */
    protected final LRUMap _untypedSchemas = new LRUMap(8,32);

    /**
     * Simple caching for schema instances, given that they are relatively expensive
     * to construct; this one is for typed schemas
     */
    protected final LRUMap _typedSchemas = new LRUMap(8,32);
    
    /*
    /**********************************************************************
    /* Life-cycle
    /**********************************************************************
     */

    public CsvMapper()
    {
        this(new CsvFactory());
    }

    public CsvMapper(CsvFactory f)
    {
        super(f);
    }

    /*
    /**********************************************************************
    /* Configuration
    /**********************************************************************
     */
    
    public CsvMapper configure(CsvGenerator.Feature f, boolean state) {
        return state ? enable(f) : disable(f);
    }

    public CsvMapper configure(CsvParser.Feature f, boolean state) {
        return state ? enable(f) : disable(f);
    }

    public CsvMapper enable(CsvGenerator.Feature f) {
        ((CsvFactory)_jsonFactory).enable(f);
        return this;
    }

    public CsvMapper enable(CsvParser.Feature f) {
        ((CsvFactory)_jsonFactory).enable(f);
        return this;
    }

    public CsvMapper disable(CsvGenerator.Feature f) {
        ((CsvFactory)_jsonFactory).disable(f);
        return this;
    }

    public CsvMapper disable(CsvParser.Feature f) {
        ((CsvFactory)_jsonFactory).disable(f);
        return this;
    }

    /*
    /**********************************************************************
    /* Additional typed accessors
    /**********************************************************************
     */

    /**
     * Overridden with more specific type, since factory we have
     * is always of type {@link CsvFactory}
     */
    @Override
    public CsvFactory getJsonFactory() {
        return getCsvFactory();
    }

    /**
     * Type-safe accessor for accessing underlying CSV-specific
     * {@link JsonFactory} implementation
     */
    public CsvFactory getCsvFactory() {
        return (CsvFactory) _jsonFactory;
    }
    
    /*
    /**********************************************************************
    /* CsvSchema construction; overrides, new methods
    /**********************************************************************
     */

    /**
     * Method that can be used to determine a CSV schema to use for given
     * POJO type, using default serialization settings including ordering.
     * Definition will not be strictly typed (that is, all columns are
     * just defined to be exposed as String tokens).
     */
    public CsvSchema schemaFor(JavaType pojoType)
    {
        return _schemaFor(pojoType, _untypedSchemas, false);
    }

    public final CsvSchema schemaFor(Class pojoType) {
        return _schemaFor(constructType(pojoType), _untypedSchemas, false);
    }

    public final CsvSchema schemaFor(TypeReference pojoTypeRef) {
        return _schemaFor(constructType(pojoTypeRef.getType()), _untypedSchemas, false);
    }

    /**
     * Method that can be used to determine a CSV schema to use for given
     * POJO type, using default serialization settings including ordering.
     * Definition WILL be strictly typed: that is, code will try to 
     * determine type limitations which may make parsing more efficient
     * (especially for numeric types like java.lang.Integer).
     */
    public CsvSchema typedSchemaFor(JavaType pojoType)
    {
        return _schemaFor(pojoType, _typedSchemas, true);
    }

    public final CsvSchema typedSchemaFor(Class pojoType) {
        return _schemaFor(constructType(pojoType), _typedSchemas, true);
    }

    public final CsvSchema typedSchemaFor(TypeReference pojoTypeRef) {
        return _schemaFor(constructType(pojoTypeRef.getType()), _typedSchemas, true);
    }
    
    @Override
    public ObjectReader reader(FormatSchema schema)
    {
        if ((schema != null) && !(schema instanceof CsvSchema)) {
            throw new IllegalArgumentException("Schema to set must be of type CsvSchema");
        }
        return super.reader(schema);
    }

    @Override
    public ObjectWriter writer(FormatSchema schema)
    {
        if ((schema != null) && !(schema instanceof CsvSchema)) {
            throw new IllegalArgumentException("Schema to set must be of type CsvSchema");
        }
        return super.writer(schema);
    }

    /**
     * Convenience method which is functionally equivalent to:
     *
     *  reader(pojoType).withSchema(schemaFor(pojoType));
     *
* that is, constructs a {@link ObjectReader} which both binds to * specified type and uses "loose" {@link CsvSchema} introspected from * specified type (one without strict inferred typing). *

* @param pojoType Type used both for data-binding (result type) and for * schema introspection. NOTE: must NOT be an array or Collection type, since * these only make sense for data-binding (like arrays of objects to bind), * but not for schema construction (no CSV types can be mapped to arrays * or Collections) */ public ObjectReader readerWithSchemaFor(Class pojoType) { JavaType type = constructType(pojoType); /* sanity check: not useful for structured types, since * schema type will need to differ from data-bind type */ if (type.isArrayType() || type.isCollectionLikeType()) { throw new IllegalArgumentException("Type can NOT be a Collection or array type"); } return reader(type).withSchema(schemaFor(type)); } /** * Convenience method which is functionally equivalent to: *

     *  reader(pojoType).withSchema(typedSchemaFor(pojoType));
     *
* that is, constructs a {@link ObjectReader} which both binds to * specified type and uses "strict" {@link CsvSchema} introspected from * specified type (one where typing is inferred). */ public ObjectReader readerWithTypedSchemaFor(Class pojoType) { JavaType type = constructType(pojoType); /* sanity check: not useful for structured types, since * schema type will need to differ from data-bind type */ if (type.isArrayType() || type.isCollectionLikeType()) { throw new IllegalArgumentException("Type can NOT be a Collection or array type"); } return reader(type).withSchema(typedSchemaFor(type)); } // deprecated, but need to override @Override public ObjectReader schemaBasedReader(FormatSchema schema) { return reader(schema); } // deprecated, but need to override @Override public ObjectWriter schemaBasedWriter(FormatSchema schema) { return writer(schema); } /* /********************************************************************** /* Internal methods /********************************************************************** */ protected CsvSchema _schemaFor(JavaType pojoType, LRUMap schemas, boolean typed) { synchronized (schemas) { CsvSchema s = schemas.get(pojoType); if (s != null) { return s; } } BeanDescription beanDesc = getSerializationConfig().introspect(pojoType); CsvSchema.Builder builder = CsvSchema.builder(); for (BeanPropertyDefinition prop : beanDesc.findProperties()) { // ignore setter-only properties: if (prop.couldSerialize()) { if (typed) { builder.addColumn(prop.getName(), _determineType(prop.getAccessor().getRawType())); } else { builder.addColumn(prop.getName()); } } } CsvSchema result = builder.build(); synchronized (schemas) { schemas.put(pojoType, result); } return result; } // should not be null since couldSerialize() returned true, so: protected CsvSchema.ColumnType _determineType(Class propType) { // First let's check certain cases that ought to be just presented as Strings... if (propType == String.class || propType == Character.TYPE || propType == Character.class) { return CsvSchema.ColumnType.STRING; } // all primitive types are good, since "numeric" allows boolean if (propType.isPrimitive() || Number.class.isAssignableFrom(propType)) { return CsvSchema.ColumnType.NUMBER; } // but in general we will just do what we can: return CsvSchema.ColumnType.NUMBER_OR_STRING; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy