有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

JavaGSON解析无引号的值

我在我的项目GSON库中使用了,一切都很好,但现在我遇到了一个问题,我需要对未引用的值使用自定义反序列化器

我有以下值,需要从json解析:

[ ["county","=", field_name], ["name", "ilike", "username"] ]

我需要使用自定义反序列化器将未引用的值解析为包装类,如:

public class StringField {
    private String value;

    public String getValue() {
        return value;
    }

}

和值将“field_name”作为字符串


共 (3) 个答案

  1. # 1 楼答案

    几年前我用另一种方式解决了这个问题(很抱歉耽搁了)。编写了符号预处理器类,用模型中的实际值替换regexp标签,如field_name,然后解析json

  2. # 2 楼答案

    问题是数据不是有效的

    JSON不允许像field_name这样的“无引号的值”字符串,Gson也不允许。要么修复输入,使其是有效的JSON(可能是"$field_name$"),要么使用能够处理类似JSON的非JSON文本的工具(即非Gson)

    这种情况不能用Custom Deserialization纠正,因为数据甚至没有正确解析为Json标记:遇到无效/非Json时,Gson将抛出异常

    至少这需要创建一个定制的JsonReader实现,该实现可以将“裸字”读取为字符串。然而,这是有问题的,因为JsonReader不符合任何专门的接口(因此它必须是子类的,oops!)并且是最终的(所以它不能被子类化,哦!)。因此,除非愿意编辑Gson库源代码:不可能

  3. # 3 楼答案

    使用下面的代码,我解析了您的JSON,没有任何问题,我让Gson决定如何解析它,只是假设它包含一个List最外层。结果是ListListString个。我不太明白为什么需要StringField

    package stackoverflow.questions;
    
    import java.util.List;
    
    import com.google.gson.*;
    
    public class Q20557131 {
    
       public static void main(String[] args){
    
          String json = "[[\"county\",\"=\", field_name], [\"name\", \"ilike\", \"username\"]]";
          Gson g = new Gson();
          List outerList = g.fromJson(json, List.class);
    
    
          List innerList = (List) outerList.get(0);
          for(Object o: innerList)
             System.out.println(o.getClass());
    
       }
    }
    

    默认情况下,Gson 2.2.4是宽松的,即使从documentation将lenient属性设置为false也是如此

    Configure this parser to be be liberal in what it accepts. By default, this parser is strict and only accepts JSON as specified by RFC 4627. Setting the parser to lenient causes it to ignore the following syntax errors:

    ....

    Strings that are unquoted or 'single quoted'.

    ...

    即使文档声明该属性默认为false,在JsonReader#fromJson的源代码中:

     public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {
        boolean isEmpty = true;
        boolean oldLenient = reader.isLenient();
        reader.setLenient(true); <  always true
        try {
          reader.peek();
          isEmpty = false;
          TypeToken<T> typeToken = (TypeToken<T>) TypeToken.get(typeOfT);
          TypeAdapter<T> typeAdapter = getAdapter(typeToken);
          T object = typeAdapter.read(reader);
          return object;
        } catch (EOFException e) {
        ...