Fastjson: 解析对象时,把字段名改了,bool类型的变量名前面的is自动去掉了

Created on 16 Jan 2015  ·  22Comments  ·  Source: alibaba/fastjson

//测试代码
class Test
{
private Boolean isTest;

public Boolean isTest() {
    return isTest;
}

public void setTest(boolean isTest) {
    this.isTest = isTest;
}

}

Test test = new Test();
test.setTest(true);
String string = JSON.toJSONString(test);
输出:{"test":true}
应该输出{"isTest":true}
这里把变量名前面的is自动去掉了,这个问题太明显了,请尽早解决,谢谢。

Most helpful comment

@lmmmd
@CodePlayer
另外,我再补充一下,我的isTest字段就是通过eclipse自动生成的,生成为:
private boolean isTest;

public boolean isTest() {
    return isTest;
}

至于为什么eclpise不自动生成为isIsTest,那就不知道了,也不知道哪个更符合所谓的规范了。

All 22 comments

补充一下,是最新的andriod发布版本。

@qicosmos 这不能算BUG,这是你自己代码不够规范,如果boolean变量名是isTest,那它的get方法应该叫isIsTest;或者你方法名就要叫isTest,那boolean变量名就得改成test(注意此处的大小写)

@qicosmos 根据JavaBean规范,如果字段property是boolean类型的,则其getter方法名为isProperty()。
所以isProperty()对应的字段名称就是property,而不是isProperty。
如果你想返回的字段名为isProperty,则getter方法应该为 isIsProperty() 或 getIsProperty()。

@lmmmd
@CodePlayer
谢谢你们的回复,是我的代码没有符合规范。但是我想说一下,这样的代码有时不小心就写出来了,导致解析的字段错误,这么严重的问题,为什么官网都没有说明呢,类似于一个潜规则吧,至少要说明一下,让人踩坑了也知道踩了什么坑。

@qicosmos 个人认为这不是坑哦,这是JavaBean规范里面规定的,学Java的貌似都应该知道吧,这是基本知识哦。另外,你们的getter和setter方法都还是自己手动写的么?没用开发工具?只要是使用开发工具,比如Eclipse/MyEclipse或者Idea,都是带有自动生成getter和setter方法的功能的。你只需要编写类里面的多个字段,然后使用快捷键操作,一秒钟就能自动生成getter和setter方法了。

@CodePlayer 你说得如此正确,我竟无言以对。
我挺奇怪的java不是一个强约束的语言,一个不合规范就导致严重的错误,这个怎么都说不过去吧。我说fastjson注明一下,凡是不合规范的就会导致严重的错误不为过吧。

@lmmmd
@CodePlayer
另外,我再补充一下,我的isTest字段就是通过eclipse自动生成的,生成为:
private boolean isTest;

public boolean isTest() {
    return isTest;
}

至于为什么eclpise不自动生成为isIsTest,那就不知道了,也不知道哪个更符合所谓的规范了。

@qicosmos 嗯,确实如此。不过你分别试试字段为 test 和 isTest 时的 getter 和 setter 方法命名,你会发现它们的方法名是相同的。但是,在根据getter方法名称反向解析出字段名称时,几乎所有框架的反向处理,都是返回 test,而不是 isTest。
如果boolean的字段名以isProperty开头,则方法名与字段名保持一致,也为isProperty()。
如果字段名首字母为大写,例如Property,则方法名为getProperty()。
这属于JavaBean里面的一些特殊约定,你可以参考JavaBean的命名规范 http://download.oracle.com/otndocs/jcp/7224-javabeans-1.01-fr-spec-oth-JSpec/。 上面是英文的,可能不好看明白,这里有一部分中文介绍:http://m.blog.csdn.net/blog/QueenJade/7104413
严格说来,这样的字段命名是不符合JavaBean规范的。

@CodePlayer 我希望我的变量名能标示它的实际类型,如果用test的话,读代码的人不能一下子就知道它是不是bool类型,所以我就命名为isTest,我不觉得这是不规范的,恰恰是为了可读性。

@qicosmos 那你需要自己改下 getter 方法的名称,改为 getIsTest() 或 isIsTest() 即可。

我是这样做的,加别名。
@JSONField(name="isPublic")
private boolean isPublic;
这样的话用is开头也没问题了。

@qicosmos 关于可读性,我的理解是:既然JavaBean要求字符声明为private,根据面向对象的封装性,将private属性封装成getter和setter方法,所以对于JavaBean的使用者来说,是这样调用的,instance.isTest() , 还是有可读性的。

Boolean property的getter 是getProperty()
boolean property的getter 是isProperty()
所以fastjson会来反推出property名字,没有问题。

这是规范,不需要质疑和讨论,只需要身体力行就可以了。

额,我想说gson就没这个问题。还有用android版本的fastjson解析不出来东西,后来没办法,不用fastjson了,哎。

如果gson如你所说得到的所谓的“正确”结果,那更应该放弃gson因为它得到了不符合规范的结果。
现在的代码习惯中,尤其因为java强类型,更不需要为变量增加前后缀来显式的标示类型特征。
即便在一些弱类型语言中用前后缀来标示类型时,对于boolean一般也不会用is作为前缀。
重复一遍,fastjson在这个场景下的结果是正确的,符合规范,没有问题。

补充:

public class Test {

    private Boolean isTest;  // 如果确为Boolean 下面是自动生成的

    public Boolean getIsTest() { // 正确的getter
        return isTest;
    }

    public void setIsTest(Boolean isTest) { // 正确的setter 注意参数
        this.isTest = isTest;
    }
}

对于boolean类型,应该选择定语表语(形容词、现在分词、过去分词)来描述定义,就不会出现你那样命名的尴尬情况。

好吧,有规则我就不说什么了。遇到的另外一个情况是android版本解析不出来结果。是通过反射加载fastjson的时候出现的。
补充一句,关于没符合所谓的规则的时候会出现问题这一点也没见声明啊,严谨一点的做法是声明一下为好。

`private boolean isTest;

public boolean isTest() {
    return isTest;
}
public void setTest(boolean isTest) {
    this.isTest = isTest;
}`

这样写,使用jackson 也无法获取正确的结果,个人认为是eclispe对javabean的实现有问题

序列化不做改动,反序列化对{"isTest":true}做了智能识别,请等待1.2.9版本吧

哎 我也是挺无语的了 我的get
set 是AS 生成的 最后放弃用isXXX 这种命名boolean 值就可以了 这个的确坑

lombok的getter、setter同样有这样的坑

有很多ide的自动生成getter和setter方法非常垃圾,完全不符合标准,会生成错误的方法名,以前用jsf时就遇到了这个坑。Boolean类型变量的getter方法是getXXX,而不是isXXX,某些ide的代码贡献者并不知道这点,导致自动生成错误的代码,然后jsf就以找不到正确的getter方法为由,说没那字段,查了好久才明白怎么回事~所以java开发者不理解一些基本标准还真是普遍现象

其实对于前段来说,很受其他的局限性影响的,比如 后台给的事 isA,并且需要回传isA,这种很尴尬,用java 可以重命名下,kotlin在 data class 或者 class 内定义,就有些问题;

fastjson: androiod 1.1.70

data class (
@field:JSONField(name = "isA")
 var A
)

class{

var A
@JSONField(name = "isA")
set
@JSONField(name = "isA")
get
}
Was this page helpful?
0 / 5 - 0 ratings