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

com.crabshue.commons.json.serialization.JsonSerializer Maven / Gradle / Ivy

The newest version!
package com.crabshue.commons.json.serialization;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

import com.crabshue.commons.exceptions.ApplicationException;
import com.crabshue.commons.exceptions.SystemException;
import com.crabshue.commons.exceptions.utils.ExceptionMessageUtils;
import com.crabshue.commons.file.FileSystemUtils;
import com.crabshue.commons.json.serialization.exceptions.JsonErrorContext;
import com.crabshue.commons.json.serialization.exceptions.JsonErrorType;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.SerializationFeature;
import lombok.NonNull;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;

/**
 * JSON object serializer.
 */
@ToString
@Slf4j
public class JsonSerializer {

    private Object objectToSerialize;

    private Class jsonSerializationView;

    private List serializationInclusions = new ArrayList<>();

    private List serializationFeatures = new ArrayList<>();
    
    private Object output;


    /**
     * Get a JSON serializer for an object.
     *
     * @param objectToSerialize the object to serialize.
     * @return the JSON serializer.
     */
    public static JsonSerializer of(@NonNull final Object objectToSerialize) {

        final JsonSerializer ret = new JsonSerializer();

        ret.objectToSerialize = objectToSerialize;
        return ret;
    }

    /**
     * Configure the JSON serializer with a serialization view to use for the serialization.
     *
     * @param jsonSerializationView the serialization view.
     * @return the JSON serializer.
     */
    public JsonSerializer withView(@NonNull final Class jsonSerializationView) {

        this.jsonSerializationView = jsonSerializationView;
        return this;
    }

    /**
     * Configure the JSON serializer with a serialization feature.
     *
     * @param serializationFeature the serialization feature.
     * @return the JSON serializer.
     */
    public JsonSerializer withSerializationFeature(@NonNull final SerializationFeature serializationFeature) {

        this.serializationFeatures.add(serializationFeature);
        return this;
    }

    /**
     * Configure the JSON serializer with a {@link JsonInclude.Include serialization inclusion rule}.
     *
     * @param serializationInclusion the serialization inclusion rule.
     * @return the JSON serializer.
     */
    public JsonSerializer withSerializationInclusion(@NonNull final JsonInclude.Include serializationInclusion) {

        this.serializationInclusions.add(serializationInclusion);
        return this;
    }

    /**
     * Configure the output for the serialization. By default, the output is a {@link String}.
     *
     * @param output the output for the serialization.
     * @return the JSON serializer.
     */
    public JsonSerializer withOutput(@NonNull final Object output) {

        this.output = output;
        return this;
    }

    /**
     * Perform the JSON serialization.
     *
     * @param  the type of the output.
     * @return the serialization result.
     */
    @SuppressWarnings("unchecked")
    public  T serialize() {

        logger.debug("Invoked JSON serializer [{}]", this);

        final ObjectWriter objectWriter = this.initializeObjectWriter();

        try {
            final Writer writer = this.initializeWriter();

            objectWriter.writeValue(writer, this.objectToSerialize);

            if (writer instanceof StringWriter) {
                this.output = writer.toString();
            }

        } catch (IOException e) {
            throw new SystemException(e);
        }

        logger.info("Serialized object [{}] to JSON", this.objectToSerialize);
        return (T) this.output;
    }

    /**
     * Initialize the writer used for the serialization.
     * The type of the writer is determined according to the type of the output.
     *
     * @return the writer.
     */
    private Writer initializeWriter() {

        final Writer ret;

        // by default the output is a string.
        if (Objects.isNull(this.output)) {
            ret = new StringWriter();
        }
        // output is a string
        else if (this.output instanceof String) {
            ret = new StringWriter();
        }
        // output is a file
        else if (this.output instanceof File || this.output instanceof Path) {

            // convert Path to File, if needed
            final File outputFile = this.output instanceof File ? (File) this.output : ((Path) this.output).toFile();
            FileSystemUtils.retrieveOrCreateFile(outputFile);
            try {
                ret = new OutputStreamWriter(new FileOutputStream(outputFile), StandardCharsets.UTF_8);
            } catch (IOException e) {
                throw new SystemException(e);
            }
        }
        // unsupported output types
        else {
            throw new ApplicationException(JsonErrorType.UNSUPPORTED_OUTPUT_FOR_JSON_SERIALIZATION)
                .addContextValue(JsonErrorContext.SUPPORTED_TYPES_FOR_JSON_SERIALIZATION, ExceptionMessageUtils.printList(Arrays.asList(String.class, File.class, Path.class), Class::getName));
        }
        return ret;
    }

    /**
     * Initialize and configure the object writer used for the JSON serialization.
     *
     * @return the object writer.
     */
    private ObjectWriter initializeObjectWriter() {

        final ObjectMapperBuilder builder = ObjectMapperBuilder.builder();

        this.serializationInclusions.forEach(builder::withSerializationInclusion);

        final ObjectMapper objectMapper = builder.build();

        ObjectWriter ret = objectMapper.writer();

        if (Objects.nonNull(jsonSerializationView)) {
            ret = ret.withView(jsonSerializationView);
        }
        for (SerializationFeature serializationFeature : this.serializationFeatures) {
            ret = ret.with(serializationFeature);
        }

        return ret;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy