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

今天是用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数组中的字符串进行替换
时间: 2024-08-09 04:50:12

使用Gson遇到的特殊字符被转码问题的相关文章

Gson 源码解读

开源库地址:https://github.com/google/gson 解读版本:2.7 Gson是一个可以用来将Java对象转换为JSON字符串的Java库.当然,它也可以把JSON字符串转换为等价的Java对象.网上已经有了不少可将Java对象转换成JSON的开源项目.但是,大多数都要求你在Java类中加入注解,如果你无法修改源码的话就比较坑爹了,此外大多数开源库并没有对泛型提供完全的支持.于是,Gson在这两个重要的设计目标下诞生了.Gson可以作用于任意的Java对象(包括接触不到源码

你真的会用Gson吗?Gson使用指南(4)

原文出处: 怪盗kidou 注:此系列基于Gson 2.4. 本次文章的主要内容: TypeAdapter JsonSerializer与JsonDeserializer TypeAdapterFactory @JsonAdapter注解 TypeAdapter与 JsonSerializer.JsonDeserializer对比 TypeAdapter实例 结语 后期预告 一.TypeAdapter TypeAdapter 是Gson自2.0(源码注释上说的是2.1)开始版本提供的一个抽象类,

前后台特殊字符中文传递乱码解决方法

页面传值前使用encodeURI转码,使用encodeURI转码后会出现特殊字符, 这时候就需要将特殊字符也转码,所以使用两次encodeURI jsp: var sort_name = encodeURI(encodeURI(url)); url=请求地址?sortName=特殊字符 Java: String sortName = (String) request.getParameter("sortname");sortName = java.net.URLDecoder.deco

Gson 使用总结 高级用法

Gson基本用法 参考:http://www.jianshu.com/p/e740196225a4 Gson提供了fromJson() 和toJson() 两个直接用于解析和生成的方法,前者实现反序列化,后者实现了序列化. //基本数据类型的解析 int i = gson.fromJson("100", int.class); //100 boolean b = gson.fromJson("true", boolean.class); // true String

Oracle处理特殊字符

检查数据库级的参数设置 select * from nls_database_parameters; 检查实例级的参数设置 select * from nls_instance_parameters 检查会话级的参数设置 select * from nls_session_parameters 检查本地的语言环境 SELECT USERENV('LANGUAGE') FROM DUAL; SIMPLIFIED CHINESE_CHINA.ZHS16GBK 开始处理 查询    的 ASCII 码

C# 过滤特殊字符

1. /// <summary> /// 过滤不安全的字符串 /// </summary> /// <param name="Str"></param> /// <returns></returns> public static string FilteSQLStr(string Str) { Str = Str.Replace("'", ""); Str = Str.Rep

JS里关于特殊字符的转义

重定向的url里含有百分号“%”,遇到了apache 找不到该文件的报错.通过查询相关文档,知道了原来是url里含有特殊字符要转码才能定位到正确的地址.比如"%"要转码为"%25","&"要转码为"%26",等等. 在javascript脚本里,有现成的转码函数可以调用,有3个:1,采用ISO Latin字符集对指定的字符串进行编码.所有的空格符.标点符号.特殊字符以及其他非ASCII字符都将被转化成%xx格式的字符编

C# 过滤HTML,脚本,数据库关键字,特殊字符

/// <summary> /// 过滤标记 /// </summary> /// <param name="NoHTML">包括HTML,脚本,数据库关键字,特殊字符的源码 </param> /// <returns>已经去除标记后的文字</returns> public static string NoHTML(string Htmlstring) { if (Htmlstring == null) { ret

.net 过滤特殊字符

/// <summary> /// 过滤标记 /// </summary> /// <param name="NoHTML">包括HTML,脚本,数据库关键字,特殊字符的源码 </param> /// <returns>已经去除标记后的文字</returns> public string NoHTML(string Htmlstring) { if (Htmlstring == null) { return &qu