使用 Jackson 的 ObjectMapper 使用具有动态类型(字符串或对象)的值解析 JSON
Parsing JSON with a value with dynamic type (either string or object) with Jackson's ObjectMapper
我是 Jackson 的新手,我在确定处理本质上是动态的 JSON 文件的最佳方式时遇到了一些问题。我知道我可以使用流式处理或树 API 来解决问题,但这会涉及很多不易维护的代码。例如,取下面两个 json 个文件:
{
something: "somethingValue"
somethingelse: "anotherValue"
url: "http://something.com"
}
和
{
something: "somethingValue"
somethingelse: "anotherValue"
url: {
service1: [
"http://something.com",
"https://something.com" ],
service2: [
"http://something2.com",
"https://something2.com" ],
}
}
第一个 json 对象在解析后的默认行为,应该将 URL 添加到 subclass 中的 service1 和 service2 url 列表 "URL"。其中第二个允许为每个指定非常具体的 urls。 url class 我打算使用的数据对象如下:
public class url {
// ideally, I would use the java.net.URL instead of String
public List<String> service1;
public List<String> service2;
// also includes getter/setters using a fluent style
...
}
还有一些其他父级 class 会有一个参数 URL 和其他第一级 json 参数。
在 jackson 中处理这个问题的最佳方法是什么?
第二个无效JSON,这是:
{
"something": "somethingValue",
"somethingelse": "anotherValue",
"url": {
"service1" : [
"http://something.com",
"https://something.com" ],
"service2" : [
"http://something2.com",
"https://something2.com" ]
}
}
您可以使用 class A 创建 it/consume 它,如下所示
class A{
String something;
String somethingElse;
B url;
}
class B{
Str service1;
List<String> service2;
}
无论如何要动态地实现任何东西,你必须把它放在列表中,因此你可以这样做而不是上面的解决方案
class A{
String something;
String somethingElse;
B url;
}
class B{
List<C> services;
}
class C{
List<String> service;
}
答案:
在与 Jackson 一起努力以简单而优雅的方式做我想做的事情之后,我最终切换到 Gson 库进行 JSON 解析。它允许我为我的 class 创建一个非常简单的自定义解串器。
可以在此处找到我所做的类似示例:
http://www.baeldung.com/gson-deserialization-guide
感谢 Jackson 的帮助和指导,但这让我意识到 Jackson 无法满足我的需求。
-斯图尔特
我最终混合了 JsonNode 来让它工作。
public class Foo {
@JsonProperty("something")
private String something;
@JsonProperty("somethingelse")
private String somethingelse;
@JsonProperty("url")
JsonNode url;
// getters setters
public static Foo parse(String jsonString) {
ObjectMapper mapper = new ObjectMapper();
Foo foo = mapper.readValue(jsonString, Foo.class);
return foo;
}
public static boolean validate(Foo foo) {
JsonNode url = foo.path("url");
if (url.isTextual()) {
// this is the first case {"url": "http://something.com"}
System.out.println(url.getTextValue());
} else {
// This is the second case
}
}
}
我是 Jackson 的新手,我在确定处理本质上是动态的 JSON 文件的最佳方式时遇到了一些问题。我知道我可以使用流式处理或树 API 来解决问题,但这会涉及很多不易维护的代码。例如,取下面两个 json 个文件:
{
something: "somethingValue"
somethingelse: "anotherValue"
url: "http://something.com"
}
和
{
something: "somethingValue"
somethingelse: "anotherValue"
url: {
service1: [
"http://something.com",
"https://something.com" ],
service2: [
"http://something2.com",
"https://something2.com" ],
}
}
第一个 json 对象在解析后的默认行为,应该将 URL 添加到 subclass 中的 service1 和 service2 url 列表 "URL"。其中第二个允许为每个指定非常具体的 urls。 url class 我打算使用的数据对象如下:
public class url {
// ideally, I would use the java.net.URL instead of String
public List<String> service1;
public List<String> service2;
// also includes getter/setters using a fluent style
...
}
还有一些其他父级 class 会有一个参数 URL 和其他第一级 json 参数。
在 jackson 中处理这个问题的最佳方法是什么?
第二个无效JSON,这是:
{
"something": "somethingValue",
"somethingelse": "anotherValue",
"url": {
"service1" : [
"http://something.com",
"https://something.com" ],
"service2" : [
"http://something2.com",
"https://something2.com" ]
}
}
您可以使用 class A 创建 it/consume 它,如下所示
class A{
String something;
String somethingElse;
B url;
}
class B{
Str service1;
List<String> service2;
}
无论如何要动态地实现任何东西,你必须把它放在列表中,因此你可以这样做而不是上面的解决方案
class A{
String something;
String somethingElse;
B url;
}
class B{
List<C> services;
}
class C{
List<String> service;
}
答案:
在与 Jackson 一起努力以简单而优雅的方式做我想做的事情之后,我最终切换到 Gson 库进行 JSON 解析。它允许我为我的 class 创建一个非常简单的自定义解串器。
可以在此处找到我所做的类似示例:
http://www.baeldung.com/gson-deserialization-guide
感谢 Jackson 的帮助和指导,但这让我意识到 Jackson 无法满足我的需求。
-斯图尔特
我最终混合了 JsonNode 来让它工作。
public class Foo { @JsonProperty("something") private String something; @JsonProperty("somethingelse") private String somethingelse; @JsonProperty("url") JsonNode url; // getters setters public static Foo parse(String jsonString) { ObjectMapper mapper = new ObjectMapper(); Foo foo = mapper.readValue(jsonString, Foo.class); return foo; } public static boolean validate(Foo foo) { JsonNode url = foo.path("url"); if (url.isTextual()) { // this is the first case {"url": "http://something.com"} System.out.println(url.getTextValue()); } else { // This is the second case } } }