package com.doghole.mess.test;

import java.lang.reflect.Field;
import java.lang.reflect.Type;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.annotation.JSONField;
import com.alibaba.fastjson2.writer.ObjectWriter;

public class FastJson2Issue2053 {

    static class Weight {
        @JSONField(serializeUsing = SelfDefinedValueSerializer.class)
        private String weight = null;
        
        private String info = null;
        
        public Weight() {}
        
        public void setWeight(String weight) {
            this.weight = weight;
        }
        
        public String getWeight() {
            return weight;
        }
        
        public void setInfo(String info) {
            this.info = info;
        }
        
        public String getInfo() {
            return info;
        }
    }
    
    static class HumanWeight extends Weight {
        
        public HumanWeight() {}
    }
    
    static class SelfDefinedValueSerializer implements ObjectWriter<Weight> {

        @Override
        public void write(JSONWriter jsonWriter, Object object, Object fieldName, Type fieldType, long features) {
            try {
                if (object != null) {
                    Field field = JSONWriter.class.getDeclaredField("rootObject");
                    if (field.trySetAccessible()) {
                        Object rootObject = field.get(jsonWriter);
                        Class<?> rootObjectClazz = rootObject.getClass();
                        if (rootObjectClazz == HumanWeight.class) {
                            jsonWriter.writeString(((String)object) + "kg/" + ((HumanWeight)rootObject).getInfo());
                        }
                        else if (rootObjectClazz == Weight.class) {
                            jsonWriter.writeString(((String)object) + "g/" + ((Weight)rootObject).getInfo());
                        }
                    }
                }
            } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }
    
    @Test
    void test() {
        Weight weight = new Weight();
        weight.setWeight("100");
        weight.setInfo("dm");
        
        Assertions.assertEquals("{\"info\":\"dm\",\"weight\":\"100g/dm\"}", JSON.toJSONString(weight));
        
        HumanWeight humanWeight = new HumanWeight();
        humanWeight.setWeight("100");
        humanWeight.setInfo("m");
        Assertions.assertEquals("{\"info\":\"m\",\"weight\":\"100kg/m\"}", JSON.toJSONString(humanWeight));
    }
    
}
