001/*
002 *  Copyright (c) 2022-2025, Mybatis-Flex (fuhai999@gmail.com).
003 *  <p>
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *  <p>
008 *  http://www.apache.org/licenses/LICENSE-2.0
009 *  <p>
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package com.mybatisflex.core.handler;
017
018import com.alibaba.fastjson2.JSON;
019import com.alibaba.fastjson2.JSONReader;
020import com.alibaba.fastjson2.JSONWriter;
021import com.alibaba.fastjson2.TypeReference;
022
023import java.lang.reflect.Modifier;
024import java.lang.reflect.ParameterizedType;
025import java.lang.reflect.Type;
026import java.util.Collection;
027
028/**
029 * @author michael
030 */
031public class Fastjson2TypeHandler extends BaseJsonTypeHandler<Object> {
032
033    private final Class<?> propertyType;
034    private Class<?> genericType;
035    private Type type;
036
037    private boolean supportAutoType = false;
038
039    public Fastjson2TypeHandler(Class<?> propertyType) {
040        this.propertyType = propertyType;
041        this.supportAutoType = propertyType.isInterface() || Modifier.isAbstract(propertyType.getModifiers());
042    }
043
044
045    public Fastjson2TypeHandler(Class<?> propertyType, Class<?> genericType) {
046        this.propertyType = propertyType;
047        this.genericType = genericType;
048        this.type = TypeReference.collectionType((Class<? extends Collection>) propertyType, genericType);
049
050        Type actualTypeArgument = ((ParameterizedType) type).getActualTypeArguments()[0];
051        if (actualTypeArgument instanceof Class) {
052            this.supportAutoType = ((Class<?>) actualTypeArgument).isInterface()
053                || Modifier.isAbstract(((Class<?>) actualTypeArgument).getModifiers());
054        }
055    }
056
057    @Override
058    protected Object parseJson(String json) {
059        if (genericType != null && Collection.class.isAssignableFrom(propertyType)) {
060            if (supportAutoType) {
061                return JSON.parseArray(json, Object.class, JSONReader.Feature.SupportAutoType);
062            } else {
063                return JSON.parseObject(json, type);
064            }
065
066        } else {
067            if (supportAutoType) {
068                return JSON.parseObject(json, Object.class, JSONReader.Feature.SupportAutoType);
069            } else {
070                return JSON.parseObject(json, propertyType);
071            }
072        }
073    }
074
075    @Override
076    protected String toJson(Object object) {
077        if (supportAutoType) {
078            return JSON.toJSONString(object
079                , JSONWriter.Feature.WriteMapNullValue
080                , JSONWriter.Feature.WriteNullListAsEmpty
081                , JSONWriter.Feature.WriteNullStringAsEmpty, JSONWriter.Feature.WriteClassName
082            );
083        } else {
084            return JSON.toJSONString(object
085                , JSONWriter.Feature.WriteMapNullValue
086                , JSONWriter.Feature.WriteNullListAsEmpty
087                , JSONWriter.Feature.WriteNullStringAsEmpty
088            );
089        }
090    }
091}