fastjson icon indicating copy to clipboard operation
fastjson copied to clipboard

问题:修改属性的类型后无法解析

Open dousp opened this issue 6 years ago • 5 comments

  • 项目第一次启动,调用public static <T> T parseObject(String text, Class<T> clazz)没有问题正常解析

  • 修改clazz中的某个属性String改为int再次调用parseObject便会出现问题,调试到FieldDeserializer.setValue(Object object, Object value) 中的method.invoke(object, value)

  • 部分信息如下

com.alibaba.fastjson.JSONException: set property error, com.....

Caused by: java.lang.reflect.InvocationTargetException
	at com.zeroturnaround.jrebelbase.facade.w.throwWrappedNoSuchMethodError(SourceFile:179)
	at com.zeroturnaround.jrebelbase.facade.w.checkMethodRemoved(SourceFile:200)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.alibaba.fastjson.parser.deserializer.FieldDeserializer.setValue(FieldDeserializer.java:110)
	... 99 more
Caused by: java.lang.NoSuchMethodError: com.test.saas.integration.dto.SmartBoxDto.setiErrorCode(I)V
	... 103 more
  • 貌似只有在这个项目里这样,换成Gson则没有这个问题
  • 开发中使用了jrebel
  • 想请教下有没有什么思路能定位出现这个问题的原因,现在是能是类型变了,重新启用项目才行。

dousp avatar Sep 13 '19 08:09 dousp

猜测与jrebel的热部署功能及fastjson的运行机制有关。 首先提一下fastjson的缓存机制:假如clazz类在项目启用后曾经被序列化/反序列化过,fastjson会缓存一份clazz类对象专属的序列化器和反序列化器,里面包含了clazz类的方法、属性等元数据,以供之后的序列化和反序列化使用。 而jrebel的热部署功能会使得即使clazz类定义被修改后,内存中仍保留原本的clazz类的标识和状态。 因此在下一次序列化、反序列化时fastjson通过这些标识和状态会认为可以直接复用之前缓存下来的数据,此时就出现了真实clazz数据与fastjson缓存的clazz元数据对应不上的情况。 当你重新启用项目时,相当于手动清除了fastjson缓存好的数据,所以可以生效。

可以试试在修改了clazz类型之后,通过调用SerializeConfigParseConfigput(clazz.class, null)方法,用null值取代原有的缓存,强制重新生成序列化器和反序列化器。

Omega-Ariston avatar Sep 17 '19 08:09 Omega-Ariston

fastjson为了快速处理,缓存了对象的类型数据和反射相关数据,你改了类型,缓存的数据就对不上了。

改了类型就重启一下再debug

kimmking avatar Sep 17 '19 09:09 kimmking

清除FastJson缓存的方法如下:

@RestController
@RequestMapping("/api")
public class SystemController {
    @ApiOperation(value = "开发时清除缓存", notes = "用于开发使用JRebel时清除FastJson的对象解析Cache")
    @RequestMapping(value = "/clearCache", method = RequestMethod.GET)
    public String clearCache() {
        SerializeConfig.getGlobalInstance().clearSerializers();
        ParserConfig.getGlobalInstance().clearDeserializers();
        return "";
    }
}

调用该方法即可清除缓存。 可以参见我的博文:解决JRebel进行代码热加载时FastJson的JsonField的缓存无法刷新问题

Vant1032 avatar Apr 18 '20 14:04 Vant1032

还有个思路,可以在开发环境,禁用asm功能

SerializeConfig.getGlobalInstance().setAsmEnable(false);

clickear avatar Dec 07 '22 06:12 clickear

清除FastJson缓存的方法如下:

@RestController
@RequestMapping("/api")
public class SystemController {
    @ApiOperation(value = "开发时清除缓存", notes = "用于开发使用JRebel时清除FastJson的对象解析Cache")
    @RequestMapping(value = "/clearCache", method = RequestMethod.GET)
    public String clearCache() {
        SerializeConfig.getGlobalInstance().clearSerializers();
        ParserConfig.getGlobalInstance().clearDeserializers();
        return "";
    }
}

调用该方法即可清除缓存。 可以参见我的博文:解决JRebel进行代码热加载时FastJson的JsonField的缓存无法刷新问题

您好,请问在FastJson2中这两个类没有了,应该如何配置呢

johnnyee avatar Aug 23 '24 13:08 johnnyee