反序列化后的JSON字段是如何一对一映射到Java对象中的字段的?

一、总览

JSON里的报文是怎么一对一赋值给OrderV1里面的属性的?

不会对应错或者对应不上吗?

这个过程是自动的吗?

后端工程师按照示例JSON报文和接口开发文档来定义了一个OrderV1,但是这里面的属性名肯定与JSON里面的字段名不完全一致,可能是相似的,然后反序列化以后就全都一对一对应的赋值上了?

package xxx;
import xxx;

/**
	* 订单接入服务接口
	* @author xxx
	*/
@Controller
@RequestMapping("/api/orderComeInto")
public class OrderComeIntoController{
	private static final Logger logger = LoggerFactory.getLogger(OrderComeIntoController.class);
	private final static String APPLICATION_JSON_UTF8_VALUE = "application/json;charset=UTF-8";
	
	@Autowired
	private orderService orderService;

	/**
		* 订单接入接口
		* @param content
		* @return
*/
	@RequestMapping(value = "/orderReceive", method = RequestMethod.POST, consumes = APPLICATION_JSON_UTF8_VALUE, produces = APPLICATION_JSON_UTF8_VALUE)
	@ResponseBody
	public Map<String, Object> orderService(@RequestBody String content){
		logger.info(content);
  		//1) 解析请求对象
  		List<OrderV1> orderV1List = JSON.parseObject(content, new TypeReference<List<OrderV1>>() {});
  		//2) 新增订单
  		Map<String, Object> result = new HashMap<>();
  		for(OrderV1 orderV1: orderV1List)
  		{
			result = orderService.receiveOrderV1(orderV1);
		  logger.info("订单处理结果:" + result);
  		}
	  return result;
	}
}
package xxx;
import xxx;

@Data
public class OrderV1 {
  private Set<String> iscpSector =new HashSet<>(Arrays.asList("0100","0251","0252","0241","0242","0211","0200"));

    // 添加一个新的字段来匹配JSON中的containerNeedList
    private List<RequestContainer> containerNeedList;

    //  订单头
    private OrderHeader order;
  
    //  货信息列表
    private List<GoodsV1> goodsList;
  
    //  预x箱列表
    private ContainerV1 containerV1;
  
    //  服务内容
    private List<Map<String, Object>> serviceList;

    public ExOrder getObject() 
	{
	  ...
	}

二、JSON解析与Java对象映射

在后端开发中,JSON解析Java对象映射通常是通过一些库来实现的。常用的库有FastjsonJacksonGson 等。

根据你提供的代码,这里使用的是Fastjson来进行JSON数据的反序列化(将JSON转换成Java对象)。

1. 反序列化过程(JSON -> Java 对象)

看这段代码:

List<OrderV1> orderV1List = JSON.parseObject(content, new TypeReference<List<OrderV1>>() {});

这是Fastjson的反序列化过程:

  • content是请求的JSON字符串,它通常是前端传递过来的数据。
  • JSON.parseObject(content, new TypeReference<List<OrderV1>>() {}) 会把这个JSON 字符串解析成一个List<OrderV1> 类型的对象。

Fastjson 会根据字段名的匹配将JSON 中的数据映射到Java对象的属性上。

2. 字段匹配与赋值

Fastjson是如何知道JSON中的字段与Java 对象的字段怎么对应的呢?主要有两个方式:

(1)字段名自动匹配:如果Java对象的属性名与JSON 中的字段名相同,Fastjson会直接把JSON中的字段值赋值给对应的Java 属性。

(2)通过注解指定映射:如果Java 对象的字段名和JSON 字段名不一致,可以使用Fastjson提供的注解来指定映射规则。

比如,假设你的OrderV1类中有以下字段:

@Data
public class OrderV1 {
    private Set<String> sector;
    private List<RequestContainer> containerNeedList;
    private OrderHeader order;
    private List<GoodsV1> goodsList;
    private ContainerV1 containerV1;
    private List<Map<String, Object>> serviceList;
}

JSON 传递的内容可能如下:

[
  {
    "sector": ["0100", "0251"],
    "containerNeedList": [{...}],
    "order": {...},
    "goodsList": [{...}],
    "containerV1": {...},
    "serviceList": [{...}]
  }
]

3. 字段映射规则

假设这个JSON中的字段名与Java类中的属性名是一样的,Fastjson就会自动完成字段值的映射。例如:

  • JSON中的sector对应Java类中的sector,Fastjson 会把JSON中的数组 ["0100", "0251"] 转换为 Set<String> 类型的集合,并赋值给OrderV1类中的sector 属性。
  • 同样的,JSON中的containerNeedList会映射到OrderV1类中的containerNeedList属性,依此类推。

4. 自动化匹配的前提

自动匹配依赖于以下两个条件:

  • 字段名相同:如果JSON中的字段名与Java对象的属性名一致,Fastjson会自动进行匹配。
  • 类型匹配:JSON中字段的类型需要与Java对象属性的类型兼容,例如JSON中的array会映射为Java中的List或Set,JSON 中的string会映射为String。

5. 字段名不一致的处理

如果JSON中的字段名与Java类中的字段名不一致,Fastjson 提供了注解@JSONField来显式指定映射关系。比如:

@Data
public class OrderV1 {
    @JSONField(name = "order_head")
    private OrderHeader order;
}

如果JSON中的字段是order_head,Fastjson会将这个字段映射到OrderV1类中的order属性。

6. 复杂类型的映射

对于复杂类型(如嵌套的对象或集合),Fastjson会递归地处理嵌套的对象或集合。例如:

  • JSON中的goodsList是一个数组,它对应OrderV1类中List<GoodsV1>,Fastjson会把JSON中的每个对象映射成GoodsV1 类的实例。
  • 如果containerNeedList是一个包含多个RequestContainer对象的数组,Fastjson也会自动将每个数组元素映射为RequestContainer对象。

三、全文总重点的精华内容(可仅看此段)

Q1:条件一(字段名相同),条件二(类型匹配),只有同时满足这两个条件,才会自动化匹配映射赋值吗?

Answer:是的,必须同时满足这两个条件才可以。

条件一是需要被硬性满足的;而关于条件二,有时候比如带引号的字符串类型赋值给数值类型也是可以的,有一定的容错率。

但是要大概其过得去,比如JSON报文里的Arrays要匹配Java对象中的Set类型或者List类型。

Q2:若JSON报文字段名和Java对象字段名仅仅是相似(比如isxxOrderType和oxxOrderType这种相似),且也满足类型匹配,会自动化匹配映射赋值吗?

不可以,字段名必须完全相同才行。

Q3:建议全部写上@JSONField注解吗?

其实倒不完全必要。

但是对于有些情况:比如JSON报文里全是a_b_c这种格式的字段名,而java对象中全是abc这种字段名的情况,建议全部统一写上@JSONField注解。

全部评论

相关推荐

评论
点赞
2
分享

创作者周榜

更多
牛客网
牛客企业服务