content: package com.alibaba.json.bvt.issue_2100;
  
  import com.alibaba.fastjson.JSON;
  import com.alibaba.fastjson.annotation.JSONField;
  import com.alibaba.fastjson.annotation.JSONType;
  import com.alibaba.fastjson.parser.DefaultJSONParser;
  import com.alibaba.fastjson.parser.JSONToken;
  import com.alibaba.fastjson.parser.ParserConfig;
  import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
  import com.alibaba.fastjson.serializer.*;
  import com.alibaba.fastjson.spi.Module;
  import org.junit.jupiter.api.Test;
  
  import java.io.IOException;
  import java.lang.reflect.Constructor;
  import java.lang.reflect.Type;
  
  import static org.junit.jupiter.api.Assertions.assertEquals;
  
  public class Issue2179 {
  
      // 场景：序列化
      @Test
      public void test_for_issue() throws Exception {
          Model1 model = new Model1(ProductType1.Phone, ProductType1.Computer);
          String out = "{\"l_k_assbalv4\":{\"code\":1,\"prompt\":\"手机\"},\"type1\":{\"code\":2,\"prompt\":\"电脑\"}}";
          assertEquals(out, JSON.toJSONString(model));
      }
  
      // 场景：使用@JSONType的deserializer = EnumAwareSerializer1.class测试自定义反序列化器
      @Test
      public void test_for_issue2() {
          String str = "{\"l_k_assbalv4\":{\"code\":1,\"prompt\":\"手机\"},\"type1\":{\"code\":2,\"prompt\":\"电脑\"}}";
          Model1 model = JSON.parseObject(str, Model1.class);
          String out = "{\"l_k_assbalv4\":{\"code\":1,\"prompt\":\"手机\"},\"type1\":{\"code\":2,\"prompt\":\"电脑\"}}";
          assertEquals(out, JSON.toJSONString(model));
      }
  
      // 场景：使用@JSONField的deserializeUsing = EnumAwareSerializer2.class测试自定义测试自定义反序化器
      @Test
      public void test_for_issue3() {
          // l_k_assbalv4对应Model2中的Type走自定义，type1走默认枚举反序列化
          String str = "{\"l_k_assbalv4\":{\"code\":1,\"prompt\":\"手机\"},\"type1\":\"Computer\"}";
          Model2 model = JSON.parseObject(str, Model2.class);
          String out = "{\"l_k_assbalv4\":{\"code\":1,\"prompt\":\"手机\"},\"type1\":{\"code\":2,\"prompt\":\"电脑\"}}";
          assertEquals(out, JSON.toJSONString(model));
      }
  
      // 场景：使用Module
      @Test
      public void test_for_issue4() {
          ParserConfig config = new ParserConfig();
  
          String str = "{\"type\":\"Phone\",\"type1\":\"Computer\"}";
          Model3 model = JSON.parseObject(str, Model3.class);
          String out = "{\"type\":{\"code\":2,\"prompt\":\"电脑\"},\"type1\":{\"code\":1,\"prompt\":\"手机\"}}";
          assertEquals(out, JSON.toJSONString(model));
      }
  
      interface EnumAware {
          int getCode();
  
          String getPrompt();
      }
  
      @JSONType(serializeEnumAsJavaBean = true, deserializer = EnumAwareSerializer1.class)
      public static enum ProductType1 implements EnumAware {
          Phone(1, "手机"), Computer(2, "电脑");
  
          public final int code;
          public final String prompt;
  
          ProductType1(int code, String prompt) {
              this.code = code;
              this.prompt = prompt;
          }
  
          @Override
          public int getCode() {
              return this.code;
          }
  
          @Override
          public String getPrompt() {
              return this.prompt;
          }
  
          public static ProductType1 get(int code) {
              switch (code) {
                  case 1:
                      return Phone;
                  case 2:
                      return Computer;
                  default:
                      return null;
              }
          }
      }
  
      public static class Model1 {
          @JSONField(name = "l_k_assbalv4")
          private ProductType1 type;
          private ProductType1 type1;
  
          public Model1(ProductType1 type, ProductType1 type1) {
              this.type = type;
              this.type1 = type1;
          }
  
          public ProductType1 getType() {
              return type;
          }
  
          public void setType(ProductType1 type) {
              this.type = type;
          }
  
          public ProductType1 getType1() {
              return type1;
          }
  
          public void setType1(ProductType1 type1) {
              this.type1 = type1;
          }
      }
  
      @JSONType(serializeEnumAsJavaBean = true)
      public static enum ProductType2 implements EnumAware {
          Phone(1, "手机"), Computer(2, "电脑");
  
          public final int code;
          public final String prompt;
  
          ProductType2(int code, String prompt) {
              this.code = code;
              this.prompt = prompt;
          }
  
          @Override
          public int getCode() {
              return this.code;
          }
  
          @Override
          public String getPrompt() {
              return this.prompt;
          }
  
          public static ProductType2 get(int code) {
              switch (code) {
                  case 1:
                      return Phone;
                  case 2:
                      return Computer;
                  default:
                      return null;
              }
          }
      }
  
      public static class Model2 {
          @JSONField(name = "l_k_assbalv4", deserializeUsing = EnumAwareSerializer2.class)
          private ProductType2 type;
          private ProductType2 type1;
  
          public Model2(ProductType2 type, ProductType2 type1) {
              this.type = type;
              this.type1 = type1;
          }
  
          public ProductType2 getType() {
              return type;
          }
  
          public void setType(ProductType2 type) {
              this.type = type;
          }
  
          public ProductType2 getType1() {
              return type1;
          }
  
          public void setType1(ProductType2 type1) {
              this.type1 = type1;
          }
      }
  
      @JSONType(serializeEnumAsJavaBean = true)
      public static enum ProductType3 implements EnumAware {
          Phone(1, "手机"), Computer(2, "电脑");
  
          public final int code;
          public final String prompt;
  
          @Override
          public int getCode() {
              return this.code;
          }
  
          ProductType3(int code, String prompt) {
              this.code = code;
              this.prompt = prompt;
          }
  
          @Override
          public String getPrompt() {
              return this.prompt;
          }
  
          public static ProductType3 get(int code) {
              switch (code) {
                  case 1:
                      return Phone;
                  case 2:
                      return Computer;
                  default:
                      return null;
              }
          }
      }
  
      public static class Model3 {
          private ProductType3 type;
          private ProductType3 type1;
  
          public Model3(ProductType3 type, ProductType3 type1) {
              this.type = type;
              this.type1 = type1;
          }
  
          public ProductType3 getType() {
              return type;
          }
  
          public void setType(ProductType3 type) {
              this.type = type;
          }
  
          public ProductType3 getType1() {
              return type1;
          }
  
          public void setType1(ProductType3 type1) {
              this.type1 = type1;
          }
      }
  
      public static class EnumAwareSerializer1
              implements ObjectDeserializer {
          @SuppressWarnings("unchecked")
          public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
              String val = StringCodec.instance.deserialze(parser, type, fieldName);
              System.out.println("-----------------EnumAwareSerializer1.deserialze-----------------------------");
              System.out.println(val);
              return (T) ProductType1.get(JSON.parseObject(val).getInteger("code"));
          }
  
          @Override
          public int getFastMatchToken() {
              return JSONToken.LITERAL_STRING;
          }
      }
  
      public static class EnumAwareSerializer2
              implements ObjectDeserializer {
          @SuppressWarnings("unchecked")
          public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
              String val = StringCodec.instance.deserialze(parser, type, fieldName);
              System.out.println("-----------------EnumAwareSerializer2.deserialze-----------------------------");
              System.out.println(val);
              return (T) ProductType2.get(JSON.parseObject(val).getInteger("code"));
          }
  
          @Override
          public int getFastMatchToken() {
              return JSONToken.LITERAL_STRING;
          }
      }
  
      public static class MyModuel
              implements Module {
  
          @SuppressWarnings("rawtypes")
          @Override
          public ObjectDeserializer createDeserializer(ParserConfig config, Class type) {
              return new ObjectDeserializer() {
                  @SuppressWarnings("unchecked")
                  @Override
                  public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
                      String val = StringCodec.instance.deserialze(parser, type, fieldName);
                      System.out.println("-----------MyModuel.deserialze------------------------");
                      System.out.println(val);
                      try {
                          Constructor c = Class.forName(type.getTypeName()).getDeclaredConstructor(ProductType3.class,
                                  ProductType3.class);
                          return (T) c.newInstance(ProductType3.Computer, ProductType3.Phone);
                      } catch (Exception e) {
                          e.printStackTrace();
                          return null;
                      }
                  }
  
                  @Override
                  public int getFastMatchToken() {
                      return JSONToken.LITERAL_STRING;
                  }
              };
          }
  
          @SuppressWarnings("rawtypes")
          @Override
          public ObjectSerializer createSerializer(SerializeConfig config, Class type) {
              return new ObjectSerializer() {
                  @Override
                  public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType,
                                    int features) throws IOException {
                      SerializeWriter out = serializer.out;
                      if (object == null) {
                          out.writeNull();
                          return;
                      }
                      System.err.println("--------------MyModuel.write-------------------------");
  
                      StringCodec.instance.write(serializer, ((ProductType3) object).name(), fieldName, fieldType,
                              features);
                  }
              };
          }
      }
  }
  