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

be.atbash.ee.security.octopus.json.AbstractJacksonJsonSerializer Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2017-2022 Rudy De Busscher (https://www.atbash.be)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package be.atbash.ee.security.octopus.json;

import be.atbash.ee.security.octopus.util.JsonbUtil;
import be.atbash.util.exception.AtbashUnexpectedException;

import javax.json.Json;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObject;
import javax.json.JsonValue;
import javax.json.bind.Jsonb;
import javax.json.bind.serializer.JsonbSerializer;
import javax.json.bind.serializer.SerializationContext;
import javax.json.stream.JsonGenerator;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;

public abstract class AbstractJacksonJsonSerializer implements JsonbSerializer {

    private static final String JACKSON_JSON_PROPERTY_ANNOTATION = "com.fasterxml.jackson.annotation.JsonProperty";

    @Override
    public void serialize(T obj, JsonGenerator jsonGenerator, SerializationContext ctx) {
        jsonGenerator = jsonGenerator.writeStartObject();

        generateJSON(jsonGenerator, obj);

        jsonGenerator.writeEnd();
    }

    private void generateJSON(JsonGenerator jsonGenerator, Object data) {
        Class currentClass = data.getClass();
        while (!currentClass.equals(Object.class)) {

            Field[] fields = currentClass.getDeclaredFields();
            for (Field field : fields) {

                boolean hasAnnotation = hasAnnotationValue(field);
                if (hasAnnotation) {
                    writeJsonField(jsonGenerator, field, data);
                }
            }
            currentClass = currentClass.getSuperclass();
        }
    }

    private void writeJsonField(JsonGenerator jsonGenerator, Field field, Object data) {
        Object fieldValue;
        try {
            field.setAccessible(true);  // FIXME Create https://github.com/atbashEE/atbash-json-smart/tree/master/accessors-smart as standalone and use this.
            fieldValue = field.get(data);
        } catch (IllegalAccessException e) {
           throw new AtbashUnexpectedException(e);
        }
        if (fieldValue == null) {
            return;  // don't write empty fields.
        }

        for (Annotation annotation : field.getAnnotations()) {
            if (annotation.annotationType().getName().equals(JACKSON_JSON_PROPERTY_ANNOTATION)) {
                String propertyName;
                try {
                    propertyName = getPropertyName(annotation, field);
                    JsonValue value = null;
                    Class type = field.getType();
                    if (type.equals(String.class)) {
                        value = Json.createValue((String) fieldValue);
                    }
                    if (type.equals(Integer.class) || type.equals(int.class)) {
                        value = Json.createValue((Integer) fieldValue);
                    }
                    if (type.equals(Long.class) || type.equals(long.class)) {
                        value = Json.createValue((Long) fieldValue);
                    }
                    if (type.equals(Double.class) || type.equals(double.class)) {
                        value = Json.createValue((Double) fieldValue);
                    }
                    if (type.equals(Boolean.class) || type.equals(boolean.class)) {
                        Boolean flag = (Boolean) fieldValue;
                        value = Json.createValue(flag ? 1 : 0);
                    }
                    if (Collection.class.isAssignableFrom(type)) {
                        Jsonb jsonb = JsonbUtil.getJsonb();

                        JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
                        Collection collection = (Collection) fieldValue;
                        collection.forEach(item -> {
                            JsonValue jsonItem;
                            if (item.getClass().getName().startsWith("java")) {
                                jsonItem = Json.createValue(item.toString());  // We assume Strong, int, etc ...
                            } else {
                                jsonItem = jsonb.fromJson(jsonb.toJson(item), JsonObject.class);
                            }
                            arrayBuilder.add(jsonItem);
                        });
                        value = arrayBuilder.build();
                    }
                    if (value == null) {
                        jsonGenerator.writeStartObject(propertyName);
                        generateJSON(jsonGenerator, fieldValue);
                        jsonGenerator.writeEnd();
                    } else {
                        jsonGenerator.write(propertyName, value);
                    }

                } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
                    throw new AtbashUnexpectedException(e);
                }

            }
        }

    }

    private String getPropertyName(Annotation annotation, Field field) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        String propertyName = annotation.getClass().getMethod("value").invoke(annotation).toString();
        if (propertyName == null || propertyName.isEmpty()) {
            propertyName = field.getName();
        }
        return propertyName;
    }

    private boolean hasAnnotationValue(Field field) {
        boolean result = false;
        for (Annotation annotation : field.getAnnotations()) {
            if (annotation.annotationType().getName().equals(JACKSON_JSON_PROPERTY_ANNOTATION)) {
                result = true;
            }
        }
        return result;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy