jackson json序列化 首字母大写 第二个字母需小写
有这样一个类:
@Setter
@Getter
@JsonNaming(value = PropertyNamingStrategy.UpperCamelCaseStrategy.class)
public class Student { private String bName; }
序列化后,希望首字母大写,如下面的测试代码:
@Test
public void contextLoads() throws IOException { Student test = new Student();
test.setBName("234234"); String s = objectMapper.writeValueAsString(test); Assert.assertEquals("{\"BName\":\"234234\"}", s); }
可实际运行后,结果与希望不一样:
org.junit.ComparisonFailure:
Expected :{"BName":"234234"}
Actual :{"Bname":"234234"}
jackson在序列化时把第二个大写字母n转成了小写,这是为什么呢?
以下是跟踪源码的过程:
直接找到:com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector#collectAll这个方法:
执行完_addFields(props)方法后:
执行完_addMethods(props)方法后:
一个是bName,一个是bname;
第一个bName取的是字段的名称,
第二个bname是取的它的set方法:
public static String okNameForIsGetter(AnnotatedMethod am, String name,
boolean stdNaming)
{
if (name.startsWith("is")) { // plus, must return a boolean
Class<?> rt = am.getRawType();
if (rt == Boolean.class || rt == Boolean.TYPE) {
return stdNaming
? stdManglePropertyName(name, 2)
: legacyManglePropertyName(name, 2);
}
}
return null;
}
根据stdNaming来决定这个name是以什么标准输出,默认的是false;
stdManglePropertyName 就是原始输出。
legacyManglePropertyName 就是规范输出。
下面的代码就是规范输出:
protected static String legacyManglePropertyName(final String basename, final int offset)
{
final int end = basename.length();
if (end == offset) { // empty name, nope
return null;
}
// next check: is the first character upper case? If not, return as is
char c = basename.charAt(offset);
char d = Character.toLowerCase(c); if (c == d) {
return basename.substring(offset);
}
// otherwise, lower case initial chars. Common case first, just one char
StringBuilder sb = new StringBuilder(end - offset);
sb.append(d);
int i = offset+1;
for (; i < end; ++i) {
c = basename.charAt(i);
d = Character.toLowerCase(c);
if (c == d) {
sb.append(basename, i, end);
break;
}
sb.append(d);
}
return sb.toString();
}
主要逻辑在for循环中,去除set后,第一个字母小写,
第二字母小写后,与第二个字母比较,如果都是小写,则直接接上,返回,
如果第二字母大写,就如我们的这种情况,就以小写的情况,接上,再去找下一个字母,直到找到小写字母为止。
意思就是为了满足驼峰命名规则,要规范输出。
如果我们的字段命名正如它的规范的话,props是只有一条记录的,因为:名称相同,就不插入了,由于咱们的名称不同,所以就有两条记录。
protected POJOPropertyBuilder _property(Map<String, POJOPropertyBuilder> props,
String implName)
{
POJOPropertyBuilder prop = props.get(implName);
if (prop == null) {
prop = new POJOPropertyBuilder(_config, _annotationIntrospector, _forSerialization,
PropertyName.construct(implName));
props.put(implName, prop);
}
return prop;
}
可是我们输出中只有一条,没有bName这条,
其实在是这里把第一条删除了。因为:
这些属性为空,导致这个字段不可见:
protected void _removeUnwantedProperties(Map<String, POJOPropertyBuilder> props)
{
Iterator<POJOPropertyBuilder> it = props.values().iterator();
while (it.hasNext()) {
POJOPropertyBuilder prop = it.next(); // First: if nothing visible, just remove altogether
if (!prop.anyVisible()) {
it.remove();
continue;
}
// Otherwise, check ignorals
if (prop.anyIgnorals()) {
// first: if one or more ignorals, and no explicit markers, remove the whole thing
if (!prop.isExplicitlyIncluded()) {
it.remove();
_collectIgnorals(prop.getName());
continue;
}
// otherwise just remove ones marked to be ignored
prop.removeIgnored();
if (!prop.couldDeserialize()) {
_collectIgnorals(prop.getName());
}
}
}
}
只剩第二记录bname,再首字母大写,所以就是Bname了。
解决方案:
第一个就是JsonProperty
@Setter
@Getter
@JsonNaming(value = PropertyNamingStrategy.UpperCamelCaseStrategy.class)
public class Student { @JsonProperty("BName")
private String bName; }
测试结果如下:
org.junit.ComparisonFailure:
Expected :{"BName":"234234"}
Actual :{"Bname":"234234","BName":"234234"}
虽然生成了BName,但是Bname仍在(加了JsonProperty就visable了)。
第二个就是配置objectMapper的MapperFeature.USE_STD_BEAN_NAMIN 如上文提到了,非规范化输出。
如下代码:
@Test
public void contextLoads() throws IOException { Student test = new Student();
test.setBName("234234");
objectMapper.configure(MapperFeature.USE_STD_BEAN_NAMING, true);
String s = objectMapper.writeValueAsString(test); Assert.assertEquals("{\"BName\":\"234234\"}", s); }
第三个方案:重写PropertyNamingStrategy:
@Test
public void contextLoads() throws IOException { Student test = new Student();
test.setBName("234234");
//objectMapper.configure(MapperFeature.USE_STD_BEAN_NAMING, true); objectMapper.setPropertyNamingStrategy(new PropertyNamingStrategy() {
private static final long serialVersionUID = 1L;
// 反序列化时调用
@Override
public String nameForSetterMethod(MapperConfig<?> config,
AnnotatedMethod method, String defaultName) {
return method.getName().substring(3);
}
// 序列化时调用
@Override
public String nameForGetterMethod(MapperConfig<?> config,
AnnotatedMethod method, String defaultName) {
return method.getName().substring(3);
}
}); String s = objectMapper.writeValueAsString(test); Assert.assertEquals("{\"BName\":\"2342344\"}", s); }
修改objectMapper的配置,要注意对其他功能的影响。
jackson json序列化 首字母大写 第二个字母需小写的更多相关文章
- python字符串的操作(去掉空格strip(),切片,查找,连接join(),分割split(),转换首字母大写, 转换字母大小写...)
#可变变量:list, 字典#不可变变量:元祖,字符串字符串的操作(去掉空格, 切片, 查找, 连接, 分割, 转换首字母大写, 转换字母大小写, 判断是否是数字字母, 成员运算符(in / not ...
- .net core json序列化首字符小写和日期格式处理
打开Startup.cs文件,在ConfigureServices方法中添加如下代码 public void ConfigureServices(IServiceCollection services ...
- Python3基础 str title 单词首字母大写,其余均为小写
Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda ...
- java中pojo对象首字母大写导致无法赋值问题
命名规范(文末附有java命名规范)中指出,属性变量命名应采用驼峰命名的方式,即首字母小写,其他单词首字母大写: 但有时候我们对接三方的接口时,想要封装实体类来接受,但是发现接收到的参数的变量首字母是 ...
- CSS通过text-transform实现大写、小写和首字母大写转换
再日常项目中可能会用到一些特殊的样式,比如大写字母转小写.小写字母转大写.首字母大写等. 可以通过 CSS 的 text-transform 属性来实现: text-transform 转换不同的文本 ...
- 使用Jackson解析首字母大写的json字符串
Jackson在解析返回的json字符串时始终报错,纠结很久之后才找到原因,原来是是由于json字符串中的字母都是首字母大写,导致jackson找不到相应的KEY. 在项目中经常使用从服务器获取的数据 ...
- javabean转成json字符首字母大写
今天写接口的时候有个需求将接口返回的json字符串首字母大写:{"SN":"","Result":""}格式, 只需要在 ...
- 如果json中的key需要首字母大写怎么解决?
一般我们命名都是驼峰式的,可是有时候和第三方接口打交道,也会遇到一些奇葩,比如首字母大写........额 这是个什么鬼,对方这么要求,那我们也得这么写呀. 于是乎,第一种方式:把类中的字段首字母大写 ...
- fastjson JSON.toJavaObject() 实体类首字母大写属性无法解析问题
fastjson JSON.toJavaObject() 实体类首字母大写属性无法解析问题
随机推荐
- BZOJ 4555 Luogu P4091 [HEOI2016/TJOI2016]求和 (第二类斯特林数)
题目链接 (luogu) https://www.luogu.org/problem/P4091 (bzoj) https://www.lydsy.com/JudgeOnline/problem.ph ...
- php curl方法 支持 http https get post cookie
//请求方式curl封装 @author Geyaru QQ 534208139 参数1:访问的URL,参数2:post数据(不填则为GET),参数3:提交的$cookies,参数4:是否返回$coo ...
- 剑指offer-Q60 n个骰子的点数
python版本代码 g_maxValue = 6 # 单个骰子最大的点数 def PrintProbability(number): ''' :param number: 骰子的个数 :return ...
- python3笔记十九:os和ospath模块
一:学习内容 os模块 ospath模块 获取指定目录下所有文件和目录 二:os模块 包含了普遍的操作系统功能,需要导入该模块:import os 当前所在位置目录结构为: 目录操作 1.获取当前目录 ...
- 六、smarty-缓存控制前的页面静态化原理
页面静态化可以实现优化服务,对大流量访问网站非常至关重要 为什么页面静态化, 1. 不去执行数据库连接 2. 不去执行SQL语句 设置按时间更新, 1. 按时间更新,如果缓存文件设置1小时 如下 ...
- 一、基础篇--1.1Java基础-什么是java的序列化和反序列化
什么是序列化和反序列化 序列化:把堆内存中的java对象数据,通过某种方式把对象存储到磁盘文件或者传递给其他网络节点.这个过程称为序列化.简单来说呢,就是将对象转换成二进流的过程. 反序列化:把磁盘 ...
- orcal 根据打分时间计算打分情况
create or replace function F_GET_TEST(in_ny in date,in_project_id in number ) return number is sRetu ...
- zookeeper源码分析:选举流程和请求处理
集群启动: QuorumPeerMain. runFromConfig() quorumPeer.start(); loadDataBase(); cnxnFactory.start(); ...
- VueLoaderPlugin作用
在webpack配置里加入new VueLoaderPlugin, 在plugin里打断点 然后debug: 在这个地方: 可以发现,在webpack初始化的阶段..webpack.js刚开始执行的时 ...
- [LeetCode] 373. Find K Pairs with Smallest Sums 找和最小的K对数字
You are given two integer arrays nums1 and nums2 sorted in ascending order and an integer k. Define ...