如何使用 jsonPath select 不同级别的 jsonfile 字段?
How to select fields in different levels of a jsonfile with jsonPath?
我想将 jsonobjcts 转换为 csv 文件。到目前为止,Wy(工作)尝试是将 json 文件加载为 JSONObject(来自 googlecode.josn-simple 库),然后使用 jsonPath 将它们转换为字符串数组,然后用于构建 csv 行。但是我遇到了 jsonPath 的问题。从给定的例子 json...
{
"issues": [
{
"key": "abc",
"fields": {
"issuetype": {
"name": "Bug",
"id": "1",
"subtask": false
},
"priority": {
"name": "Major",
"id": "3"
},
"created": "2020-5-11",
"status": {
"name": "OPEN"
}
}
},
{
"key": "def",
"fields": {
"issuetype": {
"name": "Info",
"id": "5",
"subtask": false
},
"priority": {
"name": "Minor",
"id": "2"
},
"created": "2020-5-8",
"status": {
"name": "DONE"
}
}
}
]}
我想要select以下内容:
[
"abc",
"Bug",
"Major",
"2020-5-11",
"OPEN",
"def",
"Info",
"Minor",
"2020-5-8",
"DONE"
]
csv 应如下所示:
abc,Bug,Major,2020-5-11,OPEN
def,Info,Minor,2020-5-8,DONE
我尝试了 $.issues.[*].[key,fields]
,我得到了
"abc",
{
"issuetype": {
"name": "Bug",
"id": "1",
"subtask": false
},
"priority": {
"name": "Major",
"id": "3"
},
"created": "2020-5-11",
"status": {
"name": "OPEN"
}
},
"def",
{
"issuetype": {
"name": "Info",
"id": "5",
"subtask": false
},
"priority": {
"name": "Minor",
"id": "2"
},
"created": "2020-5-8",
"status": {
"name": "DONE"
}
}
]
但是当我想 select 例如只有 "created" $.issues.[*].[key,fields.[created]
[
"2020-5-11",
"2020-5-8"
]
这是结果。
但我只是不知道如何 select "key" 例如"name" 在问题类型字段中。
我如何使用 jsonPath 做到这一点,或者是否有更好的方法来过滤 json 文件然后将其转换为 csv?
我推荐我认为更好的方法 - 即创建一组 Java classes 来表示 JSON 数据的结构。当您将 JSON 读入这些 classes 时,您可以使用标准 Java.
操作数据
我还推荐一个不同的 JSON 解析器 - 在本例中是 Jackson,但还有其他解析器。为什么?主要是熟悉度 - 稍后会看到更多相关说明。
从最终结果开始:假设我有一个名为 Container
的 class,其中包含 JSON 文件中列出的所有问题,然后我可以用以下内容填充它:
//import com.fasterxml.jackson.databind.ObjectMapper;
String jsonString = "{...}" // your JSON data as a string, for this demo.
ObjectMapper objectMapper = new ObjectMapper();
Container container = objectMapper.readValue(jsonString, Container.class);
现在我可以打印出你想要的CSV格式的所有问题如下:
container.getIssues().forEach((issue) -> {
printCsvRow(issue);
});
在这里,printCsvRow()
方法如下所示:
private void printCsvRow(Issue issue) {
String key = issue.getKey();
Fields fields = issue.getFields();
String type = fields.getIssuetype().getName();
String priority = fields.getPriority().getName();
String created = fields.getCreated();
String status = fields.getStatus().getName();
System.out.println(String.join(",", key, type, priority, created, status));
}
实际上,我会使用 CSV 库来确保记录的格式正确 - 以上只是为了说明,以显示如何访问 JSON 数据。
打印如下:
abc,Bug,Major,2020-5-11,OPEN
def,Info,Minor,2020-5-8,DONE
要仅过滤打开的记录,我可以这样做:
container.getIssues()
.stream()
.filter(issue -> issue.getFields().getStatus().getName().equals("OPEN"))
.forEach((issue) -> {
printCsvRow(issue);
});
打印如下:
abc,Bug,Major,2020-5-11,OPEN
为了启用 Jackson,我使用具有以下依赖项的 Maven:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.3</version>
</dependency>
如果您不使用 Maven,这会给我 3 个 JAR:jackson-databind
、jackson-annotations
和 jackson-core
.
为了创建我需要的嵌套 Java classes(以反映 JSON 的结构),我使用了一个工具,它使用您的示例为我生成它们 JSON.
在我的例子中,我使用了this tool,但还有其他的。
我选择了"Container"作为root的名字Javaclass; JSON 的来源类型;并选择了 Jackson 2.x 注释。我还请求了 getter 和 setter。
我将生成的 classes(字段、问题、问题类型、优先级、状态和容器)添加到我的项目中。
警告:这些 Java class 的完整性仅与示例 JSON 一样好。但是,您当然可以增强这些 class 以更准确地反映您需要处理的实际 JSON。
Jackson ObjectMapper
负责将 JSON 加载到 class 结构中。
我选择使用 Jackson 而不是 JsonPath,仅仅是因为熟悉。 JsonPath 似乎具有非常相似的对象映射功能 - 但我从未使用过 JsonPath 的这些功能。
最后说明:您可以在 JsonPath 中使用 xpath 样式谓词来访问单个数据项和项目组 - 如您在问题中所述。但是(根据我的经验)创建 Java classes 几乎总是值得的,如果你想以更灵活的方式处理所有数据 - 特别是如果这涉及转换 JSON 输入不同的输出结构。
我想将 jsonobjcts 转换为 csv 文件。到目前为止,Wy(工作)尝试是将 json 文件加载为 JSONObject(来自 googlecode.josn-simple 库),然后使用 jsonPath 将它们转换为字符串数组,然后用于构建 csv 行。但是我遇到了 jsonPath 的问题。从给定的例子 json...
{
"issues": [
{
"key": "abc",
"fields": {
"issuetype": {
"name": "Bug",
"id": "1",
"subtask": false
},
"priority": {
"name": "Major",
"id": "3"
},
"created": "2020-5-11",
"status": {
"name": "OPEN"
}
}
},
{
"key": "def",
"fields": {
"issuetype": {
"name": "Info",
"id": "5",
"subtask": false
},
"priority": {
"name": "Minor",
"id": "2"
},
"created": "2020-5-8",
"status": {
"name": "DONE"
}
}
}
]}
我想要select以下内容:
[
"abc",
"Bug",
"Major",
"2020-5-11",
"OPEN",
"def",
"Info",
"Minor",
"2020-5-8",
"DONE"
]
csv 应如下所示:
abc,Bug,Major,2020-5-11,OPEN
def,Info,Minor,2020-5-8,DONE
我尝试了 $.issues.[*].[key,fields]
,我得到了
"abc",
{
"issuetype": {
"name": "Bug",
"id": "1",
"subtask": false
},
"priority": {
"name": "Major",
"id": "3"
},
"created": "2020-5-11",
"status": {
"name": "OPEN"
}
},
"def",
{
"issuetype": {
"name": "Info",
"id": "5",
"subtask": false
},
"priority": {
"name": "Minor",
"id": "2"
},
"created": "2020-5-8",
"status": {
"name": "DONE"
}
}
]
但是当我想 select 例如只有 "created" $.issues.[*].[key,fields.[created]
[
"2020-5-11",
"2020-5-8"
]
这是结果。
但我只是不知道如何 select "key" 例如"name" 在问题类型字段中。 我如何使用 jsonPath 做到这一点,或者是否有更好的方法来过滤 json 文件然后将其转换为 csv?
我推荐我认为更好的方法 - 即创建一组 Java classes 来表示 JSON 数据的结构。当您将 JSON 读入这些 classes 时,您可以使用标准 Java.
操作数据我还推荐一个不同的 JSON 解析器 - 在本例中是 Jackson,但还有其他解析器。为什么?主要是熟悉度 - 稍后会看到更多相关说明。
从最终结果开始:假设我有一个名为 Container
的 class,其中包含 JSON 文件中列出的所有问题,然后我可以用以下内容填充它:
//import com.fasterxml.jackson.databind.ObjectMapper;
String jsonString = "{...}" // your JSON data as a string, for this demo.
ObjectMapper objectMapper = new ObjectMapper();
Container container = objectMapper.readValue(jsonString, Container.class);
现在我可以打印出你想要的CSV格式的所有问题如下:
container.getIssues().forEach((issue) -> {
printCsvRow(issue);
});
在这里,printCsvRow()
方法如下所示:
private void printCsvRow(Issue issue) {
String key = issue.getKey();
Fields fields = issue.getFields();
String type = fields.getIssuetype().getName();
String priority = fields.getPriority().getName();
String created = fields.getCreated();
String status = fields.getStatus().getName();
System.out.println(String.join(",", key, type, priority, created, status));
}
实际上,我会使用 CSV 库来确保记录的格式正确 - 以上只是为了说明,以显示如何访问 JSON 数据。
打印如下:
abc,Bug,Major,2020-5-11,OPEN
def,Info,Minor,2020-5-8,DONE
要仅过滤打开的记录,我可以这样做:
container.getIssues()
.stream()
.filter(issue -> issue.getFields().getStatus().getName().equals("OPEN"))
.forEach((issue) -> {
printCsvRow(issue);
});
打印如下:
abc,Bug,Major,2020-5-11,OPEN
为了启用 Jackson,我使用具有以下依赖项的 Maven:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.3</version>
</dependency>
如果您不使用 Maven,这会给我 3 个 JAR:jackson-databind
、jackson-annotations
和 jackson-core
.
为了创建我需要的嵌套 Java classes(以反映 JSON 的结构),我使用了一个工具,它使用您的示例为我生成它们 JSON.
在我的例子中,我使用了this tool,但还有其他的。
我选择了"Container"作为root的名字Javaclass; JSON 的来源类型;并选择了 Jackson 2.x 注释。我还请求了 getter 和 setter。
我将生成的 classes(字段、问题、问题类型、优先级、状态和容器)添加到我的项目中。
警告:这些 Java class 的完整性仅与示例 JSON 一样好。但是,您当然可以增强这些 class 以更准确地反映您需要处理的实际 JSON。
Jackson ObjectMapper
负责将 JSON 加载到 class 结构中。
我选择使用 Jackson 而不是 JsonPath,仅仅是因为熟悉。 JsonPath 似乎具有非常相似的对象映射功能 - 但我从未使用过 JsonPath 的这些功能。
最后说明:您可以在 JsonPath 中使用 xpath 样式谓词来访问单个数据项和项目组 - 如您在问题中所述。但是(根据我的经验)创建 Java classes 几乎总是值得的,如果你想以更灵活的方式处理所有数据 - 特别是如果这涉及转换 JSON 输入不同的输出结构。