JFinal中如何实现反序列化----JSON字符串向Model对象转换

2024-02-08 10:20

本文主要是介绍JFinal中如何实现反序列化----JSON字符串向Model对象转换,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

   需求: 将客户端传来的requestbody反序列化成对应的Model对象。

一、反序列化--驼峰命名

1、fastjson实现

   JFinal中没有提供反序列化的方法,因为大多数情况下,可以直接通过jar包进行转换,如利用fastjson,我们可以通过如下方式进行转换:

    JSON.parseArray(String jsonString, Class<T> class);
2、举个例子

  现有一个实体类:Book

@Data
pubilc class Book{private String bookName;private int bookPrice;
}

  将传过来的单个json数据转成对象:

String jsonStr = "{\"booktName\":\"钢铁是怎样练成的",\"bookPrice\":38.8}";
JSONArray jsonArray = JSON.parseArray(jsonStr);
Book book= (Book ) JSONObject.parseArray(jsonArray.toJSONString(), Book.class);

  将传过来的多个json数据转成对象:

String bookStr = "{\"bookList\":[{\"bookName\":\"钢铁是怎样炼成的\",\"bookPrice\":38.8},{\"bookName\":\"废柴是怎样堕落的\",\"bookPrice\":18.8}]}";
JSONObject bookJson = JSON.parseObject(bookStr );
JSONArray bookArray = bookJson .getJSONArray("bookList");
//第一种解析方式:直接解析为对象list
List<Book> booksList= JSONObject.parseArray(bookArray .toJSONString(), Book.class);

    但是如果在JFinal中这样写,编译的过程中他不会报错,但你会发现他存进去的都是空值,也就是说他在做类型转换的时候虽然识别到了这个Model,但是并不能和数据库表里的字段对应上。这是因为在数据表中,采用的是下划线"_"连接命名方式,而这种方法实际上是适用于驼峰命名的方式。

   为什么会造成这种情况呢?因为在jfinal里 Model中的getter、setter方法是按照驼峰命名的规则来生成,这时json中键值若使用数据库列名,当使用fastjson序列化时,我们会得到无法找到对应setter,从而也就无法更新其值。

接下来介绍如何解决:

二、反序列化--下划线"_"连接命名

 Object bookList= jsonObject.get("bookList");String jsonString = JSON.toJSONString( bookList, SerializerFeature.WriteMapNullValue);     List<Book> contactNoteList = parseArrayToModel(jsonString,Book.class);for (Booklist: contactNoteList) {list.set("head_id",book.get("id")).save();}

  这里设置SerializerFeature.WriteMapNullValue是因为,当传入的json以保留null值的键

//总体而言,此方法接受一个JSON数组字符串,解析它,并将每个JSON对象转换为指定模型类型的实例。它根据JSON对象中的键和值填充模型的属性,并返回这些填充好的模型的列表。public <T extends Model<T>> List<T> parseArrayToModel(String jsonString, Class<T> type) throws Exception {//初始化:List<T> list = new ArrayList<T>();JSONArray jsonArr = JSON.parseArray(jsonString);Table table = TableMapping.me().getTable(type); //使用TableMapping类的方法获取与给定模型类型相关联的表//模型解析循环:for (int i = 0; i < jsonArr.size(); i++) {T model = type.newInstance();//使用模型类型(T)的默认构造函数创建模型的新实例。JSONObject jsonObj = jsonArr.getJSONObject(i);//属性解析循环:for (String key : jsonObj.keySet()) {  //遍历JSON对象中的每个键。Class<?> colType = table.getColumnType(key);//从关联表中获取当前属性键的列类型。if (colType == null) { //如果未找到列类型(表示缺少属性),则抛出异常。throw new ActiveRecordException("The model attribute " + key + " is not exists.");}//值转换和模型填充:try {String paraValue = jsonObj.get(key) != null ? jsonObj.getString(key) : null;Object value = paraValue != null ? OpenJFinalMethod.convert(colType, paraValue) : null;  //尝试使用OpenJFinalMethod.convert方法将与当前键关联的JSON值转换为适当的类型。model.set(key, value); //使用model.set方法设置模型中的属性值。} catch (Exception e) {throw new RuntimeException("Can not convert parameter: " + key, e);}}//模型添加到列表:list.add(model); //返回包含解析后的模型的列表。}//返回语句:return list; //返回包含解析后的模型的列表。}

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.text.ParseException;
import java.text.SimpleDateFormat;/*** Convert String to other type object.*/
public class TypeConverter {private static Logger logger = LoggerFactory.getLogger(DocumentApiUtil.class);private static final String timeStampPattern = "yyyy-MM-dd HH:mm:ss";private static final String datePattern = "yyyy-MM-dd";private static final int dateLen = datePattern.length();/*** test for all types of mysql** 表单提交测试结果:* 1: 表单中的域,就算不输入任何内容,也会传过来 "", 也即永远不可能为 null.* 2: 如果输入空格也会提交上来* 3: 需要考 model中的 string属性,在传过来 "" 时是该转成 null还是不该转换,*    我想, 因为用户没有输入那么肯定是 null, 而不该是 ""** 注意: 1:当type参数不为String.class, 且参数s为空串blank的情况,*       此情况下转换结果为 null, 而不应该抛出异常*      2:调用者需要对被转换数据做 null 判断,参见 ModelInjector 的两处调用*/public static final Object convert(Class<?> type, String s) throws ParseException {// mysql type: varchar, char, enum, set, text, tinytext, mediumtext, longtextif (type == String.class) {return ("".equals(s) ? null : s);	// 用户在表单域中没有输入内容时将提交过来 "", 因为没有输入,所以要转成 null.}s = s.trim();if ("".equals(s)) {	// 前面的 String跳过以后,所有的空字符串全都转成 null,  这是合理的return null;}// 以上两种情况无需转换,直接返回, 注意, 本方法不接受null为 s 参数(经测试永远不可能传来null, 因为无输入传来的也是"")// mysql type: int, integer, tinyint(n) n > 1, smallint, mediumintif (type == Integer.class || type == int.class) {return Integer.parseInt(s);}// mysql type: bigintif (type == Long.class || type == long.class) {return Long.parseLong(s);}// java.util.Date 类型专为传统 java bean 带有该类型的 setter 方法转换做准备,万不可去掉// 经测试 JDBC 不会返回 java.util.Data 类型。java.sql.Date, java.sql.Time,java.sql.Timestamp 全部直接继承自 java.util.Data, 所以 getDate可以返回这三类数据if (type == java.util.Date.class) {if (s.length() > dateLen) {	// if (x < timeStampLen) 改用 datePattern 转换,更智能// Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]// return new java.util.Date(java.sql.Timestamp.valueOf(s).getTime());	// error under jdk 64bit(maybe)return new SimpleDateFormat(timeStampPattern).parse(s);}else {// return new java.util.Date(java.sql.Date.valueOf(s).getTime());	// error under jdk 64bitreturn new SimpleDateFormat(datePattern).parse(s);}}// mysql type: date, yearif (type == java.sql.Date.class) {if (s.length() > dateLen) {	// if (x < timeStampLen) 改用 datePattern 转换,更智能// return new java.sql.Date(java.sql.Timestamp.valueOf(s).getTime());	// error under jdk 64bit(maybe)return new java.sql.Date(new SimpleDateFormat(timeStampPattern).parse(s).getTime());}else {// return new java.sql.Date(java.sql.Date.valueOf(s).getTime());	// error under jdk 64bitreturn new java.sql.Date(new SimpleDateFormat(datePattern).parse(s).getTime());}}// mysql type: timeif (type == java.sql.Time.class) {return java.sql.Time.valueOf(s);}// mysql type: timestamp, datetimeif (type == java.sql.Timestamp.class) {if (s.length() > dateLen) {return java.sql.Timestamp.valueOf(s);}else {return new java.sql.Timestamp(new SimpleDateFormat(datePattern).parse(s).getTime());}}// mysql type: real, doubleif (type == Double.class || type == double.class) {return Double.parseDouble(s);}// mysql type: floatif (type == Float.class || type == float.class) {return Float.parseFloat(s);}// mysql type: bit, tinyint(1)if (type == Boolean.class || type == boolean.class) {String value = s.toLowerCase();if ("1".equals(value) || "true".equals(value)) {return Boolean.TRUE;}else if ("0".equals(value) || "false".equals(value)) {return Boolean.FALSE;}else {throw new RuntimeException("Can not parse to boolean type of value: " + s);}}// mysql type: decimal, numericif (type == java.math.BigDecimal.class) {return new java.math.BigDecimal(s);}// mysql type: unsigned bigintif (type == java.math.BigInteger.class) {return new java.math.BigInteger(s);}// mysql type: binary, varbinary, tinyblob, blob, mediumblob, longblob. I have not finished the test.if (type == byte[].class) {return s.getBytes();}throw new RuntimeException(type.getName() + " can not be converted, please use other type of attributes in your model!");}}

这篇关于JFinal中如何实现反序列化----JSON字符串向Model对象转换的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/690728

相关文章

使用Python将JSON,XML和YAML数据写入Excel文件

《使用Python将JSON,XML和YAML数据写入Excel文件》JSON、XML和YAML作为主流结构化数据格式,因其层次化表达能力和跨平台兼容性,已成为系统间数据交换的通用载体,本文将介绍如何... 目录如何使用python写入数据到Excel工作表用Python导入jsON数据到Excel工作表用

SpringBoot实现微信小程序支付功能

《SpringBoot实现微信小程序支付功能》小程序支付功能已成为众多应用的核心需求之一,本文主要介绍了SpringBoot实现微信小程序支付功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作... 目录一、引言二、准备工作(一)微信支付商户平台配置(二)Spring Boot项目搭建(三)配置文件

基于Python实现高效PPT转图片工具

《基于Python实现高效PPT转图片工具》在日常工作中,PPT是我们常用的演示工具,但有时候我们需要将PPT的内容提取为图片格式以便于展示或保存,所以本文将用Python实现PPT转PNG工具,希望... 目录1. 概述2. 功能使用2.1 安装依赖2.2 使用步骤2.3 代码实现2.4 GUI界面3.效

MySQL更新某个字段拼接固定字符串的实现

《MySQL更新某个字段拼接固定字符串的实现》在MySQL中,我们经常需要对数据库中的某个字段进行更新操作,本文就来介绍一下MySQL更新某个字段拼接固定字符串的实现,感兴趣的可以了解一下... 目录1. 查看字段当前值2. 更新字段拼接固定字符串3. 验证更新结果mysql更新某个字段拼接固定字符串 -

java实现延迟/超时/定时问题

《java实现延迟/超时/定时问题》:本文主要介绍java实现延迟/超时/定时问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java实现延迟/超时/定时java 每间隔5秒执行一次,一共执行5次然后结束scheduleAtFixedRate 和 schedu

Java Optional避免空指针异常的实现

《JavaOptional避免空指针异常的实现》空指针异常一直是困扰开发者的常见问题之一,本文主要介绍了JavaOptional避免空指针异常的实现,帮助开发者编写更健壮、可读性更高的代码,减少因... 目录一、Optional 概述二、Optional 的创建三、Optional 的常用方法四、Optio

在Android平台上实现消息推送功能

《在Android平台上实现消息推送功能》随着移动互联网应用的飞速发展,消息推送已成为移动应用中不可或缺的功能,在Android平台上,实现消息推送涉及到服务端的消息发送、客户端的消息接收、通知渠道(... 目录一、项目概述二、相关知识介绍2.1 消息推送的基本原理2.2 Firebase Cloud Me

Spring Boot项目中结合MyBatis实现MySQL的自动主从切换功能

《SpringBoot项目中结合MyBatis实现MySQL的自动主从切换功能》:本文主要介绍SpringBoot项目中结合MyBatis实现MySQL的自动主从切换功能,本文分步骤给大家介绍的... 目录原理解析1. mysql主从复制(Master-Slave Replication)2. 读写分离3.

Redis实现延迟任务的三种方法详解

《Redis实现延迟任务的三种方法详解》延迟任务(DelayedTask)是指在未来的某个时间点,执行相应的任务,本文为大家整理了三种常见的实现方法,感兴趣的小伙伴可以参考一下... 目录1.前言2.Redis如何实现延迟任务3.代码实现3.1. 过期键通知事件实现3.2. 使用ZSet实现延迟任务3.3

基于Python和MoviePy实现照片管理和视频合成工具

《基于Python和MoviePy实现照片管理和视频合成工具》在这篇博客中,我们将详细剖析一个基于Python的图形界面应用程序,该程序使用wxPython构建用户界面,并结合MoviePy、Pill... 目录引言项目概述代码结构分析1. 导入和依赖2. 主类:PhotoManager初始化方法:__in