在我的groovy(java)示例中,如何自动检测json字段类型?
在我的任务中,我处理传入的json并使用ResultStreamer将数据作为数据集返回。所有类型都必须写入“类型”。它们现在的定义如下:在我的groovy(java)示例中,如何自动检测json字段类型?,java,json,groovy,jsonslurper,Java,Json,Groovy,Jsonslurper,在我的任务中,我处理传入的json并使用ResultStreamer将数据作为数据集返回。所有类型都必须写入“类型”。它们现在的定义如下:def types=list.find()。价值观() *. GetClass()*。SimpleName 但这里有两个问题: 如果在json的第一个块中,某个字段有“null”,而在下一个块中有一个数字,那么该类型将被写入“null”,而不是“Integer” 如果在所有json块中,有人的字段为“null”,则会写入“null”,并且您需要在默认情况
def types=list.find()。价值观() *. GetClass()*。SimpleName
但这里有两个问题:
import groovy.json.JsonSlurper
导入ru.itrpro.xm.plugins.groovy.ResultStreamer;
类XM_PARSE_XLS{
def execute(结果跟踪程序读取器,字符串pfile){
def jsonSlurper=新的jsonSlurper()
def list=jsonSlurper.parseText pfile
List names=List.inject(new LinkedHashSet()){res,map->
res.addAll map.keySet()
物件
}托利斯先生()
def types=list.find().values()*.getClass()*.simpleName
//数据集标题的形成
reader.outputLinesSetHeaders(名称、类型);
列表。每个{e->
reader.outputLines names.collect{e[it]}
//println names.collect{e[it]}
}
//关闭数据集
reader.outputLinesEnd();
返回null;
}
静态void main(字符串…参数){
字符串pfile=“”
[{“自动”:“宝马”,
“HOME”:空,
“作业”:“},
{“自动”:“奥迪”,
“家”:135,
“作业”:null},
{“自动”:“opel1”,
“家”:10,
“作业”:null}]
"""
def SSC=新的XM_PARSE_XLS()
def res=SSC.execute(新结果跟踪程序(),pfile)
}
}
工作示例
考虑将其替换为:
def types = list.find().values()*.getClass()*.simpleName
使用此(编辑:更新有关BigDecimal/double的评论中的问题):
其思想是typeMap
将字段名映射到其类型,并默认为String
。然后:
- 迭代列表中的每个项目
- 迭代项中的每个字段
- 如果定义了字段,请在
typeMap
如果任何项具有字段的适当值,则将使用该值(假设项不能具有不同类型的值)。如果没有项目具有字段值,则
typeMap
将默认为String
非常感谢!说得很清楚!如果你在字段中输入了一个“double”类型的数字,那么为什么它会将其定义为“BigDecimal”而不是“double”?只是ResultStreamer不理解“BigDecimal”,它需要“double”。这能被纠正吗?大十进制/双精度。这似乎是一个新的/与原来不同的问题,但我已经更新了答案和GitHub repo。现在我尝试使用大型json,遇到了一个问题,即值为0的字段默认定义为“字符串”,而不是“整数”。为什么呢?0不是“null”。@Ekz0我已将代码中的if(value)
更改为if(value!=null)
。零问题是由于Groovy的真实性,其中0
被视为false
。
def types = list.find().values()*.getClass()*.simpleName
// as requested in comments:
def getTypeDef(def value) {
(value instanceof BigDecimal) ? "double" : value.getClass().simpleName
}
def typeMap = [:].withDefault { key -> "String" }
list.each { map ->
map.each { key, value ->
if (value != null) {
typeMap[key] = getTypeDef(value)
}
}
}
def types = names.collect { name -> typeMap[name] }