使用 JsonReader 读取动态 json 文件

Posted

技术标签:

【中文标题】使用 JsonReader 读取动态 json 文件【英文标题】:Using JsonReader to read dynamic json files 【发布时间】:2015-03-03 16:50:59 【问题描述】:

作为我正在创建的 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 只为“数字”提供下一个标记,但随后为 long、double 和 ints 提供特定的 getter。

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

【问题讨论】:

我不太了解这个库,但你可以调用 nextString 来获取号码,然后将该值传递给新的 BigDecimal 并让 BigDecimal 确定它是否是双精度或整数。 我曾考虑过转换,但这对我来说似乎有点难看,有点希望有其他方法可以更“原生”地工作 【参考方案1】:

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

所以。就像想法一样。您可以扩展 java.lang.Number 并在 String 中保持“原样”的值。

【讨论】:

如果我想走那条路,我可以只存储一个字符串并在调用时自己进行转换。扩号就是自找麻烦。 根据json标准,编号只是一个数字序列。因此,如果您希望获得整数,请将其保留为整数。我认为这是个好主意。此外,您还有另一种方法来检查端口号是否不是浮点数。 一般来说。如果数字有 '.'保持双倍。否则只要。 我对任何事情都不抱太大希望。这是一个配置的示例,只是为了展示我对任何事情的期望。我编写的代码的重点是让它是动态的,如果我期待某些东西,它不会让它成为动态的。【参考方案2】:

玩了一会儿之后,似乎最好的方法是只使用 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。

【讨论】:

以上是关于使用 JsonReader 读取动态 json 文件的主要内容,如果未能解决你的问题,请参考以下文章

如何在不知道 json 键的情况下使用 JsonReader 从 json 读取值

Gson使用google的JsonReader读取Json文件并转化成对象

c# JsonReader读取json字符串

带有 Json 的 Windows Phone - 从 JsonReader 读取 JObject 时出错

如何使用 ExtJS JSONReader 读取不可迭代的参数

JsonReader - 读取数组抛出预期名称但为 NULL