简体   繁体   English

使用JsonReader读取动态json文件

[英]Using JsonReader to read dynamic json files

As part of an API I am creating, I have allowed the specification of configurations (which can be any storage format, just one implementation is with Json). 作为我正在创建的API的一部分,我允许配置的规范(可以是任何存储格式,Json只是一个实现)。 As part of that, my code will have no knowledge of what the configuration truly holds. 作为其一部分,我的代码将不了解配置的真正含义。 I am using the Gson library for reading a json-implemented config, however I have hit a snag in how numbers are handled with it. 我正在使用Gson库读取json实现的配置,但是我在处理数字时遇到了麻烦。 My current code uses a recursion to read the inner objects, and contains the following: 我当前的代码使用递归读取内部对象,并且包含以下内容:

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();
}

The JsonConfigurationSection class is simply a wrapper around a Map: JsonConfigurationSection类只是Map的包装器:

class JsonConfigurationSection implements ConfigurationSection {

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

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

An example of a configuration might be 配置的示例可能是

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

The issue that has arisen is that the JsonReader only provides a next token for "Number", but then specific getters that are for longs, doubles, and ints. 出现的问题是,JsonReader仅为“ Number”提供下一个标记,但随后为long,double和ints提供特定的getter。

What would be the best way to get what that number is without any loss of data and using the "best" storage for it? 在没有任何数据丢失的情况下,使用“最佳”存储来获取该数字的最佳方法是什么? (I am willing to drop longs, but would rather see if I could keep them for consistency) (我愿意放弃多头,但宁愿看看是否可以保持一致)

Sorry for putting it as answer. 很抱歉将其作为答案。 Have no enough reputation to add comment. 没有足够的声誉来添加评论。

So. 所以。 Just as idea. 正如想法。 You can extend java.lang.Number And keep value "as is" in String. 您可以扩展java.lang.Number并在String中保留值“ as is”。

After playing around a little, it seems the best way is to just use the nextString and use the BigDecimal as was suggested by a comment: 经过一番尝试后,似乎最好的方法是仅使用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());
     }
}

This really is just checking to see if the value can fit into a int (which is the most limited of the 3 types), then a long, and if that would fail, then just keep as a double. 这实际上只是检查该值是否可以放入一个int(这是3种类型中最有限的一种)中,然后是一个长整数,如果失败,则将其保留为double。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM