使用JsonReader读取动态json文件

时间:2015-03-03 16:50:59

标签: java json gson jsonreader

作为我正在创建的API的一部分,我已经允许配置规范(可以是任何存储格式,只有一个实现与Json一起)。作为其中的一部分,我的代码将不知道配置的真正含义。 我正在使用Gson库来读取json实现的配置,但是我已经遇到了如何处理数字的问题。 我当前的代码使用递归来读取内部对象,并包含以下内容:

private JsonConfigurationSection readObject(JsonReader in) throws IOException {
    JsonConfigurationSection section = new JsonConfigurationSection();
    in.beginObject();
    while (in.peek() != JsonToken.END_OBJECT) {
        String name = in.nextName();
        switch (in.peek()) {
            case BEGIN_OBJECT: {
                section._internal.put(name, readObject(in));
            }
            break;
            case BEGIN_ARRAY: {
                in.beginArray();
                List<String> array = new LinkedList<>();
                while (in.peek() != JsonToken.END_ARRAY) {
                    array.add(in.nextString());
                }
                in.endArray();
                section._internal.put(name, array);
            }
            break;
            case BOOLEAN: {
                boolean next = in.nextBoolean();
                section._internal.put(name, next);
            }
            break;
            case NUMBER: {
                //read the next number, whether long, int, or double    
                section._internal.put(name, next);
            }
            break;
            case STRING: {
                String next = in.nextString();
                section._internal.put(name, next);
            }
            break;
        }
    }
    in.endObject();
}

JsonConfigurationSection类只是Map的一个包装器:

class JsonConfigurationSection implements ConfigurationSection {

    final Map<String, Object> _internal = new TreeMap<>();

    //methods being inherited, just getters for data from the map
}

配置示例可能是

{
  "server": {
    "ip": "127.0.0.1",
    "port": 3306
  }
  "someval": 33.4
}

出现的问题是JsonReader只为“Number”提供了下一个标记,但是为long,double和int提供了特定的getter。

在没有任何数据丢失和使用“最佳”存储空间的情况下获得该数字的最佳方法是什么? (我愿意放弃多头,但宁愿看看我是否能保持它们的一致性)

2 个答案:

答案 0 :(得分:0)

很抱歉把它作为答案。没有足够的声誉来添加评论。

因此。就像想法一样。您可以扩展java.lang.Number 并保持价值&#34;原样&#34;在String。

答案 1 :(得分:0)

玩了一下之后,似乎最好的方法是使用nextString并使用评论建议的BigDecimal:

 String line = in.nextString();
 BigDecimal decimal = new BigDecimal(line);
 try {
     section._internal.put(name, decimal.intValueExact());
 } catch (ArithmeticException e) {
     try {
         section._internal.put(name, decimal.longValueExact());
     } catch (ArithmeticException ex) {
         section._internal.put(name, decimal.doubleValue());
     }
}

这真的只是检查值是否适合int(这是3种类型中最有限的),然后是long,如果这样会失败,那么只需保留为double。