一、前言

最近老大说要新增一个试用广告的功能,我巴拉巴拉的从之前推送广告那里将代码cv过来,然后跟老大说搞定了!过一会老大说返回的json格式不对!于是乎我瞧了瞧:

{

"adsArea1":{

"adsMaterials":[

{

"animType":"99",

"materialName":"b6d767d2f8ed5d21a44b0e5886680cb9.jpg",

"materialType":"0",

"materialUrl":"http://xxx/059492d7-66f1-4052-891a-c512f957342d22.jpg",

"playTime":5,

"sort":1

}],

"areaDirection":"",

"areaId":"3721",

"areaType":"0",

"createBy":"",// 空值

"createDate":"",// 空值

"deleteFlg":"",// 空值

"height":800,

"id":"418",

"materialList":"",// 空值

"playSettingList":"",// 空值

"updateBy":"",

"updateDate":"",// 空值

"width":1280,

"x":0,

"y":0},

···

}

咋看一下,感觉没什么问题啊?然后他说之前返给我的格式不是这样的,没有这些中间的这些空值,那好吧,我看了下以往的推送历史记录里,确实是没有的,那返回的是一样的对象怎么就没有了呢?

仔细看了下,在推送的时候,保存在推送历史表里的记录是转成json字符串存储起来的 String json = JSON.toJSONString(pushAdvertisementDto);

而存在表里的数据则没有null值。而我现在直接返回的是对象。

那么问题就出在这里了~

二、直击源码

点进去JSON.class里面进去看toJSONString(pushAdvertisementDto)方法 发现可以带上一些参数:

让我们来看看SerializerFeature是一个什么东西吧:

在网上搜索了一下名词解释:

就是这个东西默认是false的,默认不输出null值的字段,如果想携带该字段,那么用这个方法就可以了:

JSON.toJSONString(Object object, SerializerFeature.WriteMapNullValue)

问题到这里就已经知道是为什么了,返回的数据没有经过FastJSON转换,因为用的是@RestController,我默认返回的对象传回去安卓那里也是json格式,但是里面的字段不对,因为业务原因就只定义了一个 PushAdvertisementDto对象返回,所以在这里用FastJSON转一下再返回就可以了。

我们接着往下看:

JSON.toJSONString()本质还是调的这个方法:

public static String toJSONString(Object object, int defaultFeatures, SerializerFeature... features) {

SerializeWriter out = new SerializeWriter((Writer)null, defaultFeatures, features); // 1

String var5;

try {

JSONSerializer serializer = new JSONSerializer(out);

serializer.write(object);// 2

var5 = out.toString();

} finally {

out.close();

}

return var5;

}

1.如果我们要输出为null值的字段,则SerializerFeature.WriteMapNullValue会被传到SerializerWriter这里做了一个初始化:

public SerializeWriter(Writer writer, int defaultFeatures, SerializerFeature... features) {

this.writer = writer;

this.buf = (char[])bufLocal.get();

if (this.buf != null) {

bufLocal.set((Object)null);

} else {

this.buf = new char[2048];

}

int featuresValue = defaultFeatures;

SerializerFeature[] var5 = features;

int var6 = features.length;

for(int var7 = 0; var7 < var6; ++var7) {

SerializerFeature feature = var5[var7];

featuresValue |= feature.getMask();

}

this.features = featuresValue;

this.computeFeatures();

}

2.让我们跟进来serializer.write(object); 里面看一看:

public final void write(Object object) {

if (object == null) {

this.out.writeNull();

} else {

Class> clazz = object.getClass();

ObjectSerializer writer = this.getObjectWriter(clazz);

try {

writer.write(this, object, (Object)null, (Type)null, 0);// 在这里做了写的操作

} catch (IOException var5) {

throw new JSONException(var5.getMessage(), var5);

}

}

}

跟进去writer.write(this, object, (Object)null, (Type)null, 0);

public interface ObjectSerializer {

void write(JSONSerializer var1, Object var2, Object var3, Type var4, int var5) throws IOException;

}

发现是个可拓展的接口,让我们看看ObjectSerializer具体的实现类JavaBeanSerializer,这里代码比较长,虽然重点关注的代码比较少,但是还是完整的贴出来:

public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {

SerializeWriter out = serializer.out;

if (object == null) {

out.writeNull();

} else if (!this.writeReference(serializer, object, features)) {

FieldSerializer[] getters;

if (out.sortField) {

getters = this.sortedGetters;

} else {

getters = this.getters;

}

SerialContext parent = serializer.context;

serializer.setContext(parent, object, fieldName, this.beanInfo.features, features);

boolean writeAsArray = this.isWriteAsArray(serializer, features);

try {

char startSeperator = writeAsArray ? 91 : 123;

char endSeperator = writeAsArray ? 93 : 125;

out.append((char)startSeperator);// 这里开始拼接输出

if (getters.length > 0 && out.isEnabled(SerializerFeature.PrettyFormat)) {

serializer.incrementIndent();

serializer.println();

}

boolean commaFlag = false;

if ((this.beanInfo.features & SerializerFeature.WriteClassName.mask) != 0 || serializer.isWriteClassName(fieldType, object)) {

Class> objClass = object.getClass();

if (objClass != fieldType) {

this.writeClassName(serializer, object);

commaFlag = true;

}

}

char seperator = commaFlag ? 44 : 0;

boolean directWritePrefix = out.quoteFieldNames && !out.useSingleQuotes;

char newSeperator = this.writeBefore(serializer, object, (char)seperator);

commaFlag = newSeperator == ',';

boolean skipTransient = out.isEnabled(SerializerFeature.SkipTransientField);

boolean ignoreNonFieldGetter = out.isEnabled(SerializerFeature.IgnoreNonFieldGetter);

for(int i = 0; i < getters.length; ++i) {

FieldSerializer fieldSerializer = getters[i];

Field field = fieldSerializer.fieldInfo.field;

FieldInfo fieldInfo = fieldSerializer.fieldInfo;

String fieldInfoName = fieldInfo.name;

Class> fieldClass = fieldInfo.fieldClass;

if ((!skipTransient || field == null || !fieldInfo.fieldTransient) && (!ignoreNonFieldGetter || field != null) && this.applyName(serializer, object, fieldInfo.name) && this.applyLabel(serializer, fieldInfo.label)) {

Object propertyValue;

try {

propertyValue = fieldSerializer.getPropertyValue(object);

} catch (InvocationTargetException var32) {

if (!out.isEnabled(SerializerFeature.IgnoreErrorGetter)) {

throw var32;

}

propertyValue = null;

}

if (this.apply(serializer, object, fieldInfoName, propertyValue)) {

String key = this.processKey(serializer, object, fieldInfoName, propertyValue);

Object originalValue = propertyValue;

propertyValue = this.processValue(serializer, fieldSerializer.fieldContext, object, fieldInfoName, propertyValue);

if (propertyValue != null || writeAsArray || fieldSerializer.writeNull || out.isEnabled(SerializerFeature.WriteMapNullValue)) {

if (propertyValue != null && out.notWriteDefaultValue) {

Class> fieldCLass = fieldInfo.fieldClass;

if (fieldCLass == Byte.TYPE && propertyValue instanceof Byte && (Byte)propertyValue == 0 || fieldCLass == Short.TYPE && propertyValue instanceof Short && (Short)propertyValue == 0 || fieldCLass == Integer.TYPE && propertyValue instanceof Integer && (Integer)propertyValue == 0 || fieldCLass == Long.TYPE && propertyValue instanceof Long && (Long)propertyValue == 0L || fieldCLass == Float.TYPE && propertyValue instanceof Float && (Float)propertyValue == 0.0F || fieldCLass == Double.TYPE && propertyValue instanceof Double && (Double)propertyValue == 0.0D || fieldCLass == Boolean.TYPE && propertyValue instanceof Boolean && !(Boolean)propertyValue) {

continue;

}

}

if (commaFlag) {

out.write(44);

if (out.isEnabled(SerializerFeature.PrettyFormat)) {

serializer.println();

}

}

if (key != fieldInfoName) {

if (!writeAsArray) {

out.writeFieldName(key, true);

}

serializer.write(propertyValue);

} else if (originalValue != propertyValue) {

if (!writeAsArray) {

fieldSerializer.writePrefix(serializer);

}

serializer.write(propertyValue);

} else {

if (!writeAsArray) {

if (directWritePrefix) {

out.write(fieldInfo.name_chars, 0, fieldInfo.name_chars.length);

} else {

fieldSerializer.writePrefix(serializer);

}

}

if (!writeAsArray) {

if (fieldClass == String.class) {

if (propertyValue == null) {

if ((out.features & SerializerFeature.WriteNullStringAsEmpty.mask) == 0 && (fieldSerializer.features & SerializerFeature.WriteNullStringAsEmpty.mask) == 0) {

out.writeNull();

} else {

out.writeString("");

}

} else {

String propertyValueString = (String)propertyValue;

if (out.useSingleQuotes) {

out.writeStringWithSingleQuote(propertyValueString);

} else {

out.writeStringWithDoubleQuote(propertyValueString, '\u0000');

}

}

} else {

fieldSerializer.writeValue(serializer, propertyValue);

}

} else {

fieldSerializer.writeValue(serializer, propertyValue);

}

}

commaFlag = true;

}

}

}

}

this.writeAfter(serializer, object, (char)(commaFlag ? ',' : '\u0000'));

if (getters.length > 0 && out.isEnabled(SerializerFeature.PrettyFormat)) {

serializer.decrementIdent();

serializer.println();

}

out.append((char)endSeperator); // 结束拼接

} catch (Exception var33) {

String errorMessage = "write javaBean error";

if (object != null) {

errorMessage = errorMessage + ", class " + object.getClass().getName();

}

if (fieldName != null) {

errorMessage = errorMessage + ", fieldName : " + fieldName;

}

if (var33.getMessage() != null) {

errorMessage = errorMessage + ", " + var33.getMessage();

}

throw new JSONException(errorMessage, var33);

} finally {

serializer.context = parent;

}

}

}

我们挑重点的看,这里我们关注out.append( )代码就可以了,中间大致就是判断一些前文说的SerializerFeature.WriteMapNullValue等条件。

跟进去out.append( )方法,在最后调用wirte方法将值付给this.buf 和this.count:

public void write(int c) {

int newcount = this.count + 1;

if (newcount > this.buf.length) {

if (this.writer == null) {

this.expandCapacity(newcount);

} else {

this.flush();

newcount = 1;

}

}

this.buf[this.count] = (char)c;

this.count = newcount;

}

再回到前面的var5 = out.toString( );SerializeWriter重写toString方法最后返回转换好的json字符串。到这里整个json转换流程就已经结束了。

三、结语

虽然只是一开始只是json格式的一个小问题,花了挺长的时间观看源码,但是感觉收获还是很大的,也很值。因为个人水平原因也不是全能看懂。。中间很长的那段源码大致就是用反射获取要转成json的对象的属性和值,然后中间经过一些条件判断,通过输出流拼接字符输出字符串。

如文中有不对的地方,欢迎指出一起讨论 ~

把执行结果转成json对象报错_于一次JSON格式错误 之 手把手带你走一波FastJSON将对象转成JSON字符串流程...相关推荐

  1. 把执行结果转成json对象报错_给Hangfire的webjob增加callback和动态判断返回结果功能设计...

    背景介绍 通常业务中需要用到定时执行功能,我用hangfire搭建了一个调度服务,这个调度服务是独立于业务逻辑的,具体可以参考文章:https://github.com/yuzd/Hangfire.H ...

  2. word2013插入excel对象报错_使用Excel中的插入对象功能在Excel中插入Word文档

    使用Excel中的插入对象功能在Excel中插入Word文档 时间:2016-05-17   作者:snow   来源:互联网 使用Excel中的插入对象功能,就可以很容易地在Excel中插入Word ...

  3. oracle 12c 报错 ora-03137 来自客户机的格式错误的TTC包被拒绝

    昨天下午,实施报了一个oracle的报错ora-03137 说是数据库在11g时没有问题,升级到12c 时,就报错了. 本地调试,看到执行完sql后,报异常,如下: 把SqL在12c的数据库执行一下, ...

  4. 把执行结果转成json对象报错_关于JSON转换成对象 报错LinkedHashMap不能直接转成对象...

    /** * 用于ajax请求,返回非list的的包装类 * @author dev4 * */ public class ObjectResult implements Serializable{ / ...

  5. word2013插入excel对象报错_在 Excel 电子表格中插入对象

    如果在 Excel 或支持 OLE 的任何程序(如 Word)之间复制信息,可以将信息复制为 链接对象 或 嵌入对象 . 链接对象与嵌入对象之间的主要区别是数据存储位置,以及对象在放置到目标位置后 目 ...

  6. android studio访问webservice如何传递类对象报错_小白学习web service,这是最最最基础的了,只用JDK还不会吗?...

    Java Web Service实践 Web Service直接翻译就是网络服务. 主要为了解决各种语言,各种系统之间不兼容,通过SOAP(简单对象访问协议)实现互联互通. 其核心就是这个SOAP,通 ...

  7. word2013插入excel对象报错_教大家Excel2013如何插入对象文件

    近日有关于Excel2013如何插入对象文件的问题受到了很多网友们的关注,大多数网友都想要知道Excel2013如何插入对象文件的具体情况,那么关于到Excel2013如何插入对象文件的相关信息,小编 ...

  8. word2013插入excel对象报错_修改Word文档中嵌入的Excel对象

    I need example code or even a 3rd party object that will allow me to get to an excel object embedded ...

  9. word2013插入excel对象报错_在Word文档中修改嵌入的Excel对象

    好吧,我做到了!感谢Remou发布的链接.在我跨过最初的障碍后,它确实提供了一些支持... 这是我的代码: WordApp.Documents.Open("C:\Report.docx&qu ...

最新文章

  1. c python.h_C++/C语言Python H
  2. Activity与Fragment的生命周期详解
  3. Load和Initialize的往死了问是一种怎样的体验
  4. 在Windows 64位下为PHP5.6.14安装redis扩展
  5. 学习笔记~~~~LinkedHashMap
  6. 【今日CS 视觉论文速览】31 Dec 2018
  7. 原生JS实现旋转轮播图+文字内容切换
  8. U产品快报 | UK8S支持K8S 1.18版本、URTC新版Webdemo上线等重要更新
  9. 关于在新办纳税人中实行增值税专用发票电子化有关事项的公告
  10. “鹏城”伴你鹏程:下届全国人工智能大赛再会!
  11. 实验:Mysql实现企业级数据库主从复制架构实战
  12. IPCAM视频数据解码并处理
  13. 人体骨骼关键点检测综述
  14. canvas实现 行人 走路的动画(完整实现)
  15. 产品经理必读的九步法
  16. python框架下的CT成像重建后处理(CIL库)
  17. 林子雨-Spark入门教程(Python版)-学习笔记(二)
  18. 全国计算机等级考试二级教程c语言程序设计考试大纲,全国计算机等级考试二级C语言程序设计考试大纲.docx...
  19. 计算机网络XP系统电路,Windows XP操作系统与计算机网络基础
  20. 计算机常用工具软件实训总结报告,计算机常用工具软件实训报告.doc

热门文章

  1. Android学习---通过内容提供者(ContentProvider)操作另外一个应用私有数据库的内容...
  2. Wine QQ2012 笔记
  3. [强烈推荐]ORACLE PL/SQL编程详解之七:程序包的创建与应用(聪明在于学习,天才在于积累!)...
  4. Redhat linux AS4 环境下iSCSI协议配置
  5. 追佛信道不如追求真理。。
  6. 让C++代码与C#代码一起生成一个单一的Assembly
  7. 7-7 全量复制开销
  8. ogg sqlserver2012 抽取不到日志_ogg抽取进程与数据字典的关系
  9. log 1用计算机怎么打开,科学计算器按键功能说明 微软附件计算器的打开方式
  10. editor.md使用php,Editor.md提示修改