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

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

今天是用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.>emptyMap(), false, false, DEFAULT_JSON_NON_EXECUTABLE,
        true, false, false, LongSerializationPolicy.DEFAULT,
        Collections.emptyList());
  }

  Gson(final Excluder excluder, final FieldNamingStrategy fieldNamingPolicy,
      final Map> instanceCreators, boolean serializeNulls,
      boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe,
      boolean prettyPrinting, boolean serializeSpecialFloatingPointValues,
      LongSerializationPolicy longSerializationPolicy,
      List 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 factories = new ArrayList();
    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数组中的字符串进行替换

转载于:https://my.oschina.net/u/998693/blog/423658

你可能感兴趣的:(使用Gson遇到的特殊字符被转码问题)