文档章节

使用Gson遇到的特殊字符被转码问题

霖_柒
 霖_柒
发布于 2015/06/01 23:35
字数 557
阅读 1114
收藏 6

今天是用gson工具的时候,发现字符串中的‘=’被替换成了unicode编程格式的‘\u003d’,查看了下gson源码,发现了gson在toString的时候的有如下操作:

private void string(String value) throws IOException {
    String[] replacements = htmlSafe ? HTML_SAFE_REPLACEMENT_CHARS : REPLACEMENT_CHARS;
    out.write("\"");
    int last = 0;
    int length = value.length();
    for (int i = 0; i < length; i++) {
      char c = value.charAt(i);
      String replacement;
      if (c < 128) {
        replacement = replacements[c];
        if (replacement == null) {
          continue;
        }
      } else if (c == '\u2028') {
        replacement = "\\u2028";
      } else if (c == '\u2029') {
        replacement = "\\u2029";
      } else {
        continue;
      }
      if (last < i) {
        out.write(value, last, i - last);
      }
      out.write(replacement);
      last = i + 1;
    }
    if (last < length) {
      out.write(value, last, length - last);
    }
    out.write("\"");
  }

其中 HTML_SAFE_REPLACEMENT_CHARS 、REPLACEMENT_CHARS 分别为:

REPLACEMENT_CHARS['"'] = "\\\"";
    REPLACEMENT_CHARS['\\'] = "\\\\";
    REPLACEMENT_CHARS['\t'] = "\\t";
    REPLACEMENT_CHARS['\b'] = "\\b";
    REPLACEMENT_CHARS['\n'] = "\\n";
    REPLACEMENT_CHARS['\r'] = "\\r";
    REPLACEMENT_CHARS['\f'] = "\\f";
    HTML_SAFE_REPLACEMENT_CHARS = REPLACEMENT_CHARS.clone();
    HTML_SAFE_REPLACEMENT_CHARS['<'] = "\\u003c";
    HTML_SAFE_REPLACEMENT_CHARS['>'] = "\\u003e";
    HTML_SAFE_REPLACEMENT_CHARS['&'] = "\\u0026";
    HTML_SAFE_REPLACEMENT_CHARS['='] = "\\u003d";
    HTML_SAFE_REPLACEMENT_CHARS['\''] = "\\u0027";

可见HTML_SAFE_REPLACEMENT_CHARS包含了REPLACEMENT_CHARS。而是使用REPLACEMENT_CHARS还是HTML_SAFE_REPLACEMENT_CHARS的关键在于boolean htmlSafe 的取值。该值是在创建Gson对象的时候传入的。

public Gson() {
    this(Excluder.DEFAULT, FieldNamingPolicy.IDENTITY,
        Collections.<Type, InstanceCreator<?>>emptyMap(), false, false, DEFAULT_JSON_NON_EXECUTABLE,
        true, false, false, LongSerializationPolicy.DEFAULT,
        Collections.<TypeAdapterFactory>emptyList());
  }

  Gson(final Excluder excluder, final FieldNamingStrategy fieldNamingPolicy,
      final Map<Type, InstanceCreator<?>> instanceCreators, boolean serializeNulls,
      boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe,
      boolean prettyPrinting, boolean serializeSpecialFloatingPointValues,
      LongSerializationPolicy longSerializationPolicy,
      List<TypeAdapterFactory> typeAdapterFactories) {
    this.constructorConstructor = new ConstructorConstructor(instanceCreators);
    this.serializeNulls = serializeNulls;
    this.generateNonExecutableJson = generateNonExecutableGson;
    this.htmlSafe = htmlSafe;
    this.prettyPrinting = prettyPrinting;

无参的构造函数,会将htmlSafe设置成true,也就是我们通过 Gson gson = new Gson(); 生成的gson对象toString的时候会进行HTML_SAFE_REPLACEMENT_CHARS的字符替换。

带有参数的构造函数,htmlSafe字段只有传入的参数决定。而带有参数的Gson构造函数只由GsonBuilder.create()方法调用。

public Gson create() {
    List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>();
    factories.addAll(this.factories);
    Collections.reverse(factories);
    factories.addAll(this.hierarchyFactories);
    addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, factories);

    return new Gson(excluder, fieldNamingPolicy, instanceCreators,
        serializeNulls, complexMapKeySerialization,
        generateNonExecutableJson, escapeHtmlChars, prettyPrinting,
        serializeSpecialFloatingPointValues, longSerializationPolicy, factories);
  }

可见GsonBuilder对象的escapeHtmlChars属性控制着htmlSafe。而GsonBuilder的escapeHtmlChars的默认值为true。但可以通过GsonBuilder对象的disableHtmlEscaping方法来将escapeHtmlChars置为false,而后在调用create方法生成Gson对象,这样生成的Gson对象在toString的时候就只会替换REPLACEMENT_CHARS数组。

public GsonBuilder disableHtmlEscaping() {
    this.escapeHtmlChars = false;
    return this;
  }

总结:

生成的Gson对象的方法:

①Gson gson = new Gson();

gson.toString(obj);

会对HTML_SAFE_REPLACEMENT_CHARS数组中的字符串进行替换

②GsonBuilder gsonBuilder = new GsonBuilder();

Gson gson = builder.create();

gson.toString(obj);

会对HTML_SAFE_REPLACEMENT_CHARS数组中的字符串进行替换

③ GsonBuilder gsonBuilder = new GsonBuilder();

 gsonBuilder.disableHtmlEscaping();

 Gson gson = builder.create();   

 gson.toString(obj);

会对REPLACEMENT_CHARS数组中的字符串进行替换

© 著作权归作者所有

霖_柒
粉丝 1
博文 15
码字总数 19843
作品 0
福州
私信 提问
Gson解析服务端返回的多种类型的JSON

遇到几种Json类型,使用Gson通过自定义解析器解析一下几种类型的返回数据。 JSON示例 返回Json中data为空 返回Json中data值为null 返回Json中data为对象类型 返回Json中的data为集合类型 返回...

秦川小将
2018/02/09
0
0
关于jsp访问路径带中文值需encodeURI两次的原因

jsp往后台传值的时候,一般可以通过路径传值和ajax传值。 其中通过ajax post传值不会出现中文乱码现象,但路径传值如果不通过特殊的编码,后台可能获取到的是一串乱码。 encodeURI可以帮助我...

文文1
2016/07/12
292
0
Invalid character found in the request target. The valid characters are defined in RFC 3986

问题描述 请求参数含有特殊字符时后台报这个错误: 查了资料原因是 Tomcat在 7.0.73, 8.0.39, 8.5.7 版本后,添加了对于http头的验证。 安全定义 安全字符 英文字母 : a-zA-Z 数字 : 0-9 特殊...

ol_O_O_lo
2018/12/03
209
0
拉风的道长/SJson

##Sjon的初衷是什么? 有没有遇到服务器接口返回数据总是不固定的情况? //这是接口的定义:ArrayList students;int counts; //这是他喵的服务器返回:{"students" :[], "counts":0} //这也是...

拉风的道长
2015/09/01
0
0
WebView loadData出错(奇怪的设计)

今天遇到一个奇怪的问题。 我使用WebView加载一个网页。 方法1. 直接使用 loadUrl() 方法,没有问题。完全可以。 方法2. 使用loadData()方法,出现问题,无法显示。 方法3. 使用loadDataWit...

晨曦之光
2012/03/01
429
0

没有更多内容

加载失败,请刷新页面

加载更多

OpenStack 简介和几种安装方式总结

OpenStack :是一个由NASA和Rackspace合作研发并发起的,以Apache许可证授权的自由软件和开放源代码项目。项目目标是提供实施简单、可大规模扩展、丰富、标准统一的云计算管理平台。OpenSta...

小海bug
今天
4
0
DDD(五)

1、引言 之前学习了解了DDD中实体这一概念,那么接下来需要了解的就是值对象、唯一标识。值对象,值就是数字1、2、3,字符串“1”,“2”,“3”,值时对象的特征,对象是一个事物的具体描述...

MrYuZixian
今天
6
0
数据库中间件MyCat

什么是MyCat? 查看官网的介绍是这样说的 一个彻底开源的,面向企业应用开发的大数据库集群 支持事务、ACID、可以替代MySQL的加强版数据库 一个可以视为MySQL集群的企业级数据库,用来替代昂贵...

沉浮_
今天
4
0
解决Mac下VSCode打开zsh乱码

1.乱码问题 iTerm2终端使用Zsh,并且配置Zsh主题,该主题主题需要安装字体来支持箭头效果,在iTerm2中设置这个字体,但是VSCode里这个箭头还是显示乱码。 iTerm2展示如下: VSCode展示如下: 2...

HelloDeveloper
今天
7
0
常用物流快递单号查询接口种类及对接方法

目前快递查询接口有两种方式可以对接,一是和顺丰、圆通、中通、天天、韵达、德邦这些快递公司一一对接接口,二是和快递鸟这样第三方集成接口一次性对接多家常用快递。第一种耗费时间长,但是...

程序的小猿
今天
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部