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

hydraql.shaded.fastjson2.writer.FieldWriterObject Maven / Gradle / Ivy

The newest version!
package hydraql.shaded.fastjson2.writer;

import hydraql.shaded.fastjson2.JSONException;
import hydraql.shaded.fastjson2.JSONWriter;
import hydraql.shaded.fastjson2.codec.FieldInfo;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.*;
import java.util.concurrent.atomic.AtomicIntegerArray;
import java.util.concurrent.atomic.AtomicLongArray;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

abstract class FieldWriterObject
        extends FieldWriter {
    volatile Class initValueClass;
    volatile ObjectWriter initObjectWriter;
    final boolean unwrapped;
    final boolean array;
    final boolean number;

    static final AtomicReferenceFieldUpdater initValueClassUpdater = AtomicReferenceFieldUpdater.newUpdater(
            FieldWriterObject.class,
            Class.class,
            "initValueClass"
    );

    static final AtomicReferenceFieldUpdater initObjectWriterUpdater = AtomicReferenceFieldUpdater.newUpdater(
            FieldWriterObject.class,
            ObjectWriter.class,
            "initObjectWriter"
    );

    protected FieldWriterObject(
            String name,
            int ordinal,
            long features,
            String format,
            String label,
            Type fieldType,
            Class fieldClass,
            Field field,
            Method method
    ) {
        super(name, ordinal, features, format, label, fieldType, fieldClass, field, method);
        this.unwrapped = (features & FieldInfo.UNWRAPPED_MASK) != 0;

        if (fieldClass == Currency.class) {
            this.initValueClass = fieldClass;
            this.initObjectWriter = ObjectWriterImplCurrency.INSTANCE_FOR_FIELD;
        }

        array = fieldClass.isArray()
                || Collection.class.isAssignableFrom(fieldClass)
                || fieldClass == AtomicLongArray.class
                || fieldClass == AtomicIntegerArray.class;
        number = Number.class.isAssignableFrom(fieldClass);
    }

    @Override
    public ObjectWriter getInitWriter() {
        return initObjectWriter;
    }

    @Override
    public boolean unwrapped() {
        return unwrapped;
    }

    @Override
    public ObjectWriter getObjectWriter(JSONWriter jsonWriter, Class valueClass) {
        if (initValueClass == null || initObjectWriter == ObjectWriterBaseModule.VoidObjectWriter.INSTANCE) {
            ObjectWriter formattedWriter = null;
            if (format == null) {
                JSONWriter.Context context = jsonWriter.getContext();
                boolean fieldBased = ((features | context.getFeatures()) & JSONWriter.Feature.FieldBased.mask) != 0;
                formattedWriter = context.getProvider().getObjectWriterFromCache(valueClass, valueClass, fieldBased);
            }

            if (formattedWriter == null) {
                formattedWriter = FieldWriter.getObjectWriter(fieldType, fieldClass, format, null, valueClass);
            }

            if (formattedWriter == null) {
                boolean success = initValueClassUpdater.compareAndSet(this, null, valueClass);
                formattedWriter = jsonWriter.getObjectWriter(valueClass);
                if (success) {
                    initObjectWriterUpdater.compareAndSet(this, null, formattedWriter);
                }
                return formattedWriter;
            } else {
                if (initObjectWriter == null) {
                    boolean success = initValueClassUpdater.compareAndSet(this, null, valueClass);
                    if (success) {
                        initObjectWriterUpdater.compareAndSet(this, null, formattedWriter);
                    }
                }
                return formattedWriter;
            }
        } else {
            boolean typeMatch = initValueClass == valueClass;
            if (!typeMatch && initValueClass.isPrimitive()) {
                typeMatch = (initValueClass == int.class && valueClass == Integer.class)
                        || (initValueClass == long.class && valueClass == Long.class)
                        || (initValueClass == boolean.class && valueClass == Boolean.class)
                        || (initValueClass == short.class && valueClass == Short.class)
                        || (initValueClass == byte.class && valueClass == Byte.class)
                        || (initValueClass == float.class && valueClass == Float.class)
                        || (initValueClass == double.class && valueClass == Double.class)
                        || (initValueClass == char.class && valueClass == Character.class);
            }

            if (typeMatch) {
                ObjectWriter objectWriter;
                if (initObjectWriter == null) {
                    if (Map.class.isAssignableFrom(valueClass)) {
                        if (fieldClass.isAssignableFrom(valueClass)) {
                            objectWriter = ObjectWriterImplMap.of(fieldType, valueClass);
                        } else {
                            objectWriter = ObjectWriterImplMap.of(valueClass);
                        }
                    } else {
                        objectWriter = jsonWriter.getObjectWriter(valueClass);
                    }
                    initObjectWriterUpdater.compareAndSet(this, null, objectWriter);
                } else {
                    objectWriter = initObjectWriter;
                }
                return objectWriter;
            } else {
                if (Map.class.isAssignableFrom(valueClass)) {
                    if (fieldClass.isAssignableFrom(valueClass)) {
                        return ObjectWriterImplMap.of(fieldType, valueClass);
                    } else {
                        return ObjectWriterImplMap.of(valueClass);
                    }
                } else {
                    return jsonWriter.getObjectWriter(valueClass);
                }
            }
        }
    }

    @Override
    public boolean write(JSONWriter jsonWriter, T object) {
        long features = this.features | jsonWriter.getFeatures();

        if (!fieldClassSerializable && (features & JSONWriter.Feature.IgnoreNoneSerializable.mask) != 0) {
            return false;
        }

        Object value;
        try {
            value = getFieldValue(object);
        } catch (RuntimeException error) {
            if (jsonWriter.isIgnoreErrorGetter()) {
                return false;
            }
            throw error;
        }

        if (value == null) {
            if ((features & JSONWriter.Feature.WriteNulls.mask) != 0
                    && (features & JSONWriter.Feature.NotWriteDefaultValue.mask) == 0
            ) {
                writeFieldName(jsonWriter);
                if (array) {
                    jsonWriter.writeArrayNull();
                } else if (number) {
                    jsonWriter.writeNumberNull();
                } else if (fieldClass == Appendable.class
                        || fieldClass == StringBuffer.class
                        || fieldClass == StringBuilder.class) {
                    jsonWriter.writeStringNull();
                } else {
                    jsonWriter.writeNull();
                }
                return true;
            } else {
                return false;
            }
        }

        if ((features & JSONWriter.Feature.IgnoreNoneSerializable.mask) != 0 && !(value instanceof Serializable)) {
            return false;
        }

        boolean refDetect = jsonWriter.isRefDetect(value);
        if (refDetect) {
            if (value == object) {
                writeFieldName(jsonWriter);
                jsonWriter.writeReference("..");
                return true;
            }

            String refPath = jsonWriter.setPath(this, value);
            if (refPath != null) {
                writeFieldName(jsonWriter);
                jsonWriter.writeReference(refPath);
                jsonWriter.popPath(value);
                return true;
            }
        }

        Class valueClass = value.getClass();
        if (valueClass == byte[].class) {
            writeBinary(jsonWriter, (byte[]) value);
            return true;
        }

        ObjectWriter valueWriter = getObjectWriter(jsonWriter, valueClass);
        if (valueWriter == null) {
            throw new JSONException("get objectWriter error : " + valueClass);
        }

        if (unwrapped) {
            if (value instanceof Map) {
                for (Iterator it = ((Map) value).entrySet().iterator(); it.hasNext(); ) {
                    Map.Entry entry = it.next();
                    String entryKey = entry.getKey().toString();
                    Object entryValue = entry.getValue();
                    if (entryValue == null) {
                        if ((features & JSONWriter.Feature.WriteNulls.mask) == 0) {
                            continue;
                        }
                    }

                    jsonWriter.writeName(entryKey);
                    jsonWriter.writeColon();
                    if (entryValue == null) {
                        jsonWriter.writeNull();
                    } else {
                        Class entryValueClass = entryValue.getClass();
                        ObjectWriter entryValueWriter = jsonWriter.getObjectWriter(entryValueClass);
                        entryValueWriter.write(jsonWriter, entryValue);
                    }
                }

                if (refDetect) {
                    jsonWriter.popPath(value);
                }
                return true;
            }

            if (valueWriter instanceof ObjectWriterAdapter) {
                ObjectWriterAdapter writerAdapter = (ObjectWriterAdapter) valueWriter;
                List fieldWriters = writerAdapter.fieldWriters;
                for (FieldWriter fieldWriter : fieldWriters) {
                    fieldWriter.write(jsonWriter, value);
                }
                return true;
            }
        }

        writeFieldName(jsonWriter);
        boolean jsonb = jsonWriter.isJSONB();
        if ((this.features & JSONWriter.Feature.BeanToArray.mask) != 0) {
            if (jsonb) {
                valueWriter.writeArrayMappingJSONB(jsonWriter, value, fieldName, fieldType, this.features);
            } else {
                valueWriter.writeArrayMapping(jsonWriter, value, fieldName, fieldType, this.features);
            }
        } else {
            if (jsonb) {
                valueWriter.writeJSONB(jsonWriter, value, fieldName, fieldType, this.features);
            } else {
                valueWriter.write(jsonWriter, value, fieldName, fieldType, this.features);
            }
        }

        if (refDetect) {
            jsonWriter.popPath(value);
        }
        return true;
    }

    @Override
    public void writeValue(JSONWriter jsonWriter, T object) {
        Object value = getFieldValue(object);
        if (value == null) {
            jsonWriter.writeNull();
            return;
        }

        Class valueClass = value.getClass();
        ObjectWriter valueWriter;
        if (initValueClass == null) {
            initValueClass = valueClass;
            valueWriter = jsonWriter.getObjectWriter(valueClass);
            initObjectWriterUpdater.compareAndSet(this, null, valueWriter);
        } else {
            if (initValueClass == valueClass) {
                valueWriter = initObjectWriter;
            } else {
                valueWriter = jsonWriter.getObjectWriter(valueClass);
            }
        }
        if (valueWriter == null) {
            throw new JSONException("get value writer error, valueType : " + valueClass);
        }

        boolean refDetect = jsonWriter.isRefDetect() && !ObjectWriterProvider.isNotReferenceDetect(valueClass);

        if (refDetect) {
            if (value == object) {
                jsonWriter.writeReference("..");
                return;
            }

            String refPath = jsonWriter.setPath(fieldName, value);
            if (refPath != null) {
                jsonWriter.writeReference(refPath);
                jsonWriter.popPath(value);
                return;
            }
        }

        if (jsonWriter.isJSONB()) {
            if (jsonWriter.isBeanToArray()) {
                valueWriter.writeArrayMappingJSONB(jsonWriter, value, fieldName, fieldClass, features);
            } else {
                valueWriter.writeJSONB(jsonWriter, value, fieldName, fieldClass, features);
            }
        } else {
            valueWriter.write(jsonWriter, value, fieldName, fieldClass, features);
        }

        if (refDetect) {
            jsonWriter.popPath(value);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy