首页 > 解决方案 > Gson Parser 接受 toString 表示而不是 Json 语法

问题描述

在调试一段将字符串反序列化为对象的代码时,我意识到那里的 JSON 解析正在使用 toString 表示而不是对象的 json 表示。

波乔:

import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class Pojo {

    int a;
    String b;
}

解析逻辑:

Gson gsonInstance =
        new GsonBuilder()
                .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
                .setDateFormat("yyyy-MM-dd")
                .create();
String json2 = "{a=5, b=field}";
Pojo obj = gsonInstance.fromJson(json2, Pojo.class);

System.out.println(obj);

当我向 Pojo 添加包含“:”的字段时,这开始中断。喜欢日期。

围绕这个问题有两个问题:1)Gson 是如何支持这个的?我找不到任何文档。一样的。2)我如何使用这种 toString 类型的实现来处理我之前提到的与日期相关的问题?我尝试为 Java 转义字符串,但没有帮助。

标签: javajsongsondeserializationjson-deserialization

解决方案


这是 Gson 的一个特性,它实际上是有文档的,但文档有点隐藏。参考:Gson.java。JSON 反序列化最终调用是

public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException

在代码正文中,请参阅:

reader.setLenient(true);

现在参考JsonReader.java

 public final void setLenient(boolean lenient)

该方法的 javadoc 说明如下:

/** * 将此解析器配置为自由接受的内容。默认情况下, * 此解析器是严格的,仅接受 RFC 4627 指定的 JSON。将 * 解析器设置为 lenient 会导致它忽略以下语法错误:* *

    *
  • 以非执行 * 前缀开头的流,")]}'\n". *
  • 包含多个顶级值的流。通过严格的解析,* 每个流必须只包含一个顶级值。*
  • 任何类型的顶级值。使用严格解析,顶级 * 值必须是对象或数组。*
  • 数字可能是 {@link Double#isNaN() NaNs} 或 {@link * Double#isInfinite() infinities}。*
  • 以 {@code //} 或 {@code #} 开头和 * 以换行符结尾的行尾注释。*
  • C 风格的注释以 {@code /*} 开头并以 * {@code *}{@code /} 结尾。此类注释可能不会嵌套。*
  • 未加引号或 {@code 'singlequoted'} 的名称。*
  • 未加引号或 {@code 'singlequoted'} 的字符串。*
  • 由 {@code ;} 而不是 {@code ,} 分隔的数组元素。*
  • 不必要的数组分隔符。这些被解释为好像 null * 是省略的值。*
  • 名称和值由 {@code =} 或 {@code =>} 分隔,而不是 * {@code :}。*
  • 由 {@code ;} 而不是 {@code ,} 分隔的名称/值对。*
*/

以上就是 Gson 解析你的字符串并反序列化的原因。

如果您的名称/值(未加引号)有任何“:”,则上述内容将不起作用,因为 Gson 将(在您的情况下)解释为 name=[value 或 anotherName???]:value (Gson 不是那么宽松)。

使用正确的有效 JSON 并反序列化。


推荐阅读