- 使用 Spring Initializr 创建 Spring Boot 应用程序
- 在Spring Boot中配置Cassandra
- 在 Spring Boot 上配置 Tomcat 连接池
- 将Camel消息路由到嵌入WildFly的Artemis上
web工程中,数据交互是不可避免的,相比xml,json是现在流行的数据交互。
在调试接口中,发现返回字段的大小写不是我所期望的,原本应该返回的nNum字段变成了nnum,这样就导致和前端约定的有出入了。
web工程中,比较流行的框架是springMVC+spring+mybatis。数据交互由springMVC完成,但是springMVC也不是自己序列化json的,它将这个工作交给了jackson。
jackson对object进行序列化的过程中确实存在key大写变小写的问题。看我娓娓道来。
这里只对jackson的序列化原理做阐述,其他的序列化工具不一定是相同的原理,不可套用。
众所周知,json的数据格式是,key:value的形式,现在的问题就出现在key的大小写这边。
下面我们对其进行一定的测试:
object中的field都有其对应的get,set方法,一般都会选择是IDE自动生成。如下图所示:
其运行的结果当然没有问题:
jackson会获取field对应的get方法方法名,比如getXxx,然后进行将get进行截断,变成Xxx,最后将其小写,变成xxx。
如果我们将xxx改成xXx,但是没有更改其get方法,key仍然是xxx,并不是我们期望的xXx:
网上的很多博客基本都只提及大写转小写,其实不然,jackson只会将连续的大写转换成小写,如果中间断了,之后的大写字符也不会处理了,并且jackson是从开头检测的,如果开头就是小写,那么之后的大写字符也不会处理了。测试如下:
正如网上的博客所说,你需要在field和其对应的get方法上加上对应的标签,然后jackson在序列化的时候就会以你的field名称为key:
总结spring的序列化工作是由jackson完成(你也可以配置其他的序列化工具)
jackson序列化的key定义与field名称无关,反而和其get方法名称有关
jackson的大写转小写从开头检测,并且一定是连续的
jackson的这种序列化机制是可以避免的,这样可以以field名称作为key
jackson包提供了java对象与json相互转换的API。
Jackson要求java对象是一个POJO对象,即它是一个普通JavaBean对象。此外,如果字段是用private修饰的,则必须有getXXX()方法,否则字段用public修饰。
json常见格式如下
{
"key1" : value,
"key2" : [...],
"key3" : {...}
}
jackson把JavaBean对象的每个字段映射为json的键,json键值由JavaBean的getXXX()方法确定。
json键值从形式上看,可以分为基本类型(字符串、数值)、数组、字典。当JavaBean的字段声明为基本类型时对应json的基本类型,当JavaBean声明为数组或链表时对应json的数组类型,当JavaBean声明为字典或对象时对应json的字典类型。
定义一个符合JavaBean规则的类
package com.weixia.Json;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class Bean {
private String name;
private int[] stature;
private Friend friend;
private ArrayList<String> song;
private Map<String,Integer> score = new HashMap<String,Integer>();
public Bean(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setStature(int[] stature) {
this.stature = stature;
}
public int[] getStature() {
return this.stature;
}
public void setSong(ArrayList<String> song) {
this.song = song;
}
public ArrayList<String> getSong() {
return this.song;
}
public void setFriend(Friend friend) {
this.friend = friend;
}
public Friend getFriend() {
return this.friend;
}
public void addScore(String subject,Integer score) {
this.score.put(subject, score);
}
public Map getScore() {
return this.score;
}
}
class Friend {
public String name;
public int age;
}
将Bean对象序列化为json如下
package com.weixia.Json;
import java.util.ArrayList;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
public class App
{
public static void main( String[] args ) throws Exception
{
Bean bean = new Bean("Album");
ObjectMapper mapper = new ObjectMapper();
bean.setStature(new int[] {88,60,89});
ArrayList<String> song = new ArrayList<String>();
song.add("奇异恩典");
song.add("东京的都");
bean.setSong(song);
Friend friend = new Friend();
friend.name = "小明";
friend.age = 24;
bean.setFriend(friend);
bean.addScore("Math", 100);
bean.addScore("PE", 88);
mapper.configure(SerializationFeature.INDENT_OUTPUT, true); //格式化输出
mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true); //键按自然顺序输出
mapper.setSerializationInclusion(Include.NON_EMPTY); //忽略POJO中属性为空的字段
mapper.writeValue(System.out, bean);
}
}
json文件如下:
{
"name": "weixia",
"age": 24,
"stature":[89,66,89],
"friend":{
"name":"zhiye",
"age":24
},
"test":""
}
定义一个符合JaveBean规则的类
package com.weixia.Json;
public class People {
private String name;
private int age;
private Friend friend;
private int[] stature;
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
public Friend getFriend() {
return this.friend;
}
public int[] getStature() {
return this.stature;
}
}
class Friend {
public String name;
public int age;
}
将json反序列化为java对象
package com.weixia.Json;
import java.io.File;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Json2Bean {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); //忽略未知的属性
People people = mapper.readValue(new File("F:\\test.json"), People.class);
System.out.println(people.getName());
System.out.println(people.getAge());
System.out.println(people.getFriend());
int[] stature = people.getStature();
for (int num : stature) {
System.out.println(num);
}
}
}
目标:我想在设备上安装我的应用程序时从 iTunes 链接中获取我的自定义参数(引荐来源网址)。 iTunes 链接看起来像这样: https://itunes.apple.com/in/app/co
三维数据的获取方式 RGBD相机和深度图 代码展示:在pcl中,把点云转为深度图,并保存和可视化 三维数据的获取方式 在计算机视觉和遥感领域,点云可以通过四种主要的技术获得, (1)根据图像衍生而得,
这是拍摄 out of context所以看起来有点奇怪,但我有以下数据结构: use std::marker::PhantomData; pub struct Map { data: Vec
如何在用户注册时事通讯时运行此跟踪代码? var google_conversion_id = xxxxxx; var google_conversion_language = "e
对于我们的招聘网站,我们为每个与员工编号相关的员工提供了唯一的URL。然后,他们可以将其唯一的URL分配给其个性化页面。想知道是否有一种简单/最佳的方法来跟踪每个员工的表单生成的提交数量。即Todd通
网站 Saritias 情况 我的客户希望跟踪 Google Adwords 转化情况。当客户点击广告、访问网站,然后使用第 3 方预订小部件 ( ResDiary ) 预订餐 table 时,即可实
在我的 react PWA 上,我想在发送表单数据之后跟踪 Google Adwords 中的转化。我已经使用 react-ga 模块来跟踪使用 UA-xxxxxx 编号的页面浏览量。现在我有一个 A
不知道你是否能帮忙。 我们有一个电子商务网站。我们与 PayPal 和 WorldPay 集成进行付款,并将 secure.worldpay.com 和 paypal.com 添加到 Analytic
所以我已经安装了 Google Analytics,现在我想跟踪转化,但我希望转化代码仅在用户来自特定来源/媒介时运行,并忽略其余部分。可能吗? 最佳答案 您可以在分析过程中使用过滤器和/或分段来隔离
我想在同一页面上跟踪 2 个不同的 onclick 转化。 Google 的示例跟踪代码如下所示: /* */ 示例 onclick 代码如下所示: DO
我有一个 VueJS 应用程序,用户在其中提交表单。使用 Vue-resource 将数据发送到服务器。我需要告诉 Google 这是一次转换。 Google 给我的是一个脚本,告诉我放入“thank
我是一名优秀的程序员,十分优秀!