具有目标值或键的对象的 jq 过滤器不存在 简化

问题描述

我有 jsonlines 数据,我想找到 1. value is empty object 或 2. key is not exist 。在下面的示例中,我想知道 .items.spec.resource={} 或 .items.spec.limits|requests which key 不存在的项目的结果。

@Bean
public FlatFileItemReader<DAOUser> reader() {
    DefaultConversionService conversionService = new DefaultConversionService();
    conversionService.addConverter(new Converter<String,Date>() { // java.sql.Date
        @Override
        public Date convert(String s) {
            return Date.valueOf(s);
        }
    });
    BeanWrapperFieldSetMapper<DAOUser> fieldSetMapper = new BeanWrapperFieldSetMapper<>();
    fieldSetMapper.setConversionService(conversionService);
    fieldSetMapper.settargettype(DAOUser.class);

    FlatFileItemReader<DAOUser> reader = new FlatFileItemReader<>();
    reader.setResource(new ClassPathResource("users.csv"));
    reader.setLineMapper(new DefaultLineMapper<DAOUser>() {{
        setLinetokenizer(new DelimitedLinetokenizer() {{
            setNames(new String[] { "dateIntegration","email","fullname","matricule","password","username" });
        }});
        setFieldSetMapper(fieldSetMapper);
    }});
    return reader;
}
data='{"items":[{"Metadata":{"name":"pod01"},"spec":{"containers":[{"name":"con01_01","resources":{"limits":{"cpu":"100m"},"requests":{"cpu":"100m"}}},{"name":"con01_02","requests":{"cpu":"100m"}}}]}},{"Metadata":{"name":"pod02"},"spec":{"containers":[{"name":"con02_01",{"name":"con02_02","resources":{"limits":{"cpu":"100m"}}}]}},{"Metadata":{"name":"pod03"},"spec":{"containers":[{"name":"con03_01",{"name":"con03_02","resources":{}}]}}]}'
list=$(echo $data | jq '.items[] | select(.spec.containers[].resources.requests == null or  .spec.containers[].resources.limits == null or .spec.containers[].resources == {})')

结果来了

echo $list 

repeat 部分没看懂,估计是条件的原因,上面条件的那部分怎么才能得到,我想过滤一下Metadata和spec.containers符合条件的部分。

>

解决方法

根据您的解释性评论,您似乎可以使用 jq "$-variables" 实现您想要的:

jq -c '
.items[]
| .metadata.name as $podname
| .spec.containers[] 
| select(.resources.requests == null or 
         .resources.limits == null or 
         .resources == {})
| [$podname,.name]
'

使用您的数据,上面产生的输出将是:

["pod02","con02_02"]
["pod03","con03_02"]

简化

对第三个条件(.resources == {})的测试其实是多余的,所以上面的jq过滤器相当于:

.items[]
| .metadata.name as $podname
| .spec.containers[] 
| select(.resources | (.requests == null or .limits == null ))
| [$podname,.name]

键的存在

要检查密钥是否存在,通常使用 has/1 是合适的,因为 {} | .key 的计算结果为 null。因此,您可能希望将上面的 select() 替换为:

select( any(.resources | has("requests","limits"); not) )