Java 记录在设计上不能从另一个对象继承(请参阅为什么 Java 记录不支持继承?)。因此,我想知道实现以下目标的最佳方法是什么。
给定我的 JSON 数据包含具有一些通用数据唯一数据的对象。例如,文字、宽度和高度在所有形状中,但根据类型,它们可以具有其他字段:
{
"name": "testDrawing",
"shapes": [
{
"type": "shapeA",
"width": 100,
"height": 200,
"label": "test"
},
{
"type": "shapeB",
"width": 100,
"height": 200,
"length": 300
},
{
"type": "shapeC",
"width": 100,
"height": 200,
"url": "www.test.be",
"color": "#FF2233"
}
]
}
在“传统”Java中,您可以使用
BaseShape with width and height
ShapeA extends BaseShape with label
ShapeB extends BaseShape with length
ShapeC extends BaseShape with URL and color
但我有点固执,真的很想用记录。
我的解决方案现在如下所示:
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public record Drawing(
@JsonProperty("name")
String name,
@JsonProperty("shapes")
@JsonDeserialize(using = TestDeserializer.class)
List<Object> shapes // I don't like the Objects here...
) {
}
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public record ShapeA (
@JsonProperty("type") String type,
@JsonProperty("width") Integer width,
@JsonProperty("height") Integer height,
@JsonProperty("label") String label
) {
}
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public record ShapeB(
@JsonProperty("type") String type,
@JsonProperty("width") Integer width,
@JsonProperty("height") Integer height,
@JsonProperty("length") Integer length
) {
}
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public record ShapeC(
@JsonProperty("type") String type,
@JsonProperty("width") Integer width,
@JsonProperty("height") Integer height,
@JsonProperty("url") String url,
@JsonProperty("color") String color
) {
}
我不喜欢重复的代码,这是一种不好的做法......但最后我可以用这个帮助程序类加载它:
public class TestDeserializer extends JsonDeserializer {
ObjectMapper mapper = new ObjectMapper();
@Override
public List<Object> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
List<Object> rt = new ArrayList<>();
JsonNode node = jsonParser.getCodec().readTree(jsonParser);
if (node instanceof ArrayNode array) {
for (Iterator<JsonNode> it = array.elements(); it.hasNext(); ) {
JsonNode childNode = it.next();
rt.add(getShape(childNode));
}
} else {
rt.add(getShape(node));
}
return rt;
}
private Object getShape(JsonNode node) {
var type = node.get("type").asText();
switch (type) {
case "shapeA":
return mapper.convertValue(node, ShapeA.class);
case "shapeB":
return mapper.convertValue(node, ShapeB.class);
case "shapeC":
return mapper.convertValue(node, ShapeC.class);
default:
throw new IllegalArgumentException("Shape could not be parsed");
}
}
}
这个测试被证明工作正常:
@Test
void fromJsonToJson() throws IOException, JSONException {
File f = new File(this.getClass().getResource("/test.json").getFile());
String jsonFromFile = Files.readString(f.toPath());
ObjectMapper mapper = new ObjectMapper();
Drawing drawing = mapper.readValue(jsonFromFile, Drawing.class);
String jsonFromObject = mapper.writeValueAsString(drawing);
System.out.println("Original:\n" + jsonFromFile.replace("\n", "").replace(" ", ""));
System.out.println("Generated:\n" + jsonFromObject);
assertAll(
//() -> assertEquals(jsonFromFile, jsonFromObject),
() -> assertEquals("testDrawing", drawing.name()),
() -> assertTrue(drawing.shapes().get(0) instanceof ShapeA),
() -> assertTrue(drawing.shapes().get(1) instanceof ShapeB),
() -> assertTrue(drawing.shapes().get(2) instanceof ShapeC)
);
}
使用杰克逊库和Java记录实现此目的的最佳方法是什么?
额外的旁注:我还需要能够以与原始格式相同的格式写回 JSON。
如果使用常规类,则可以批注父类以包含类型名称作为属性。
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
public class Shape {
}
@JsonTypeName("shapeA")
public class ShapeA extends Shape {
}
问题内容: 我的样子如下: 现在,每个元素具有相同的结构(假设一个POJO称为MessageDefault.java)。那么我怎么能把所有东西都当作一个??呢? 我正在使用gson进行解析。我也不能更改JSON响应。 编辑:: MessageDefault.java 它只是一切的结构。但是在JSON中,的每个子项都有不同的名称,例如POJO MessageDefault.java中所反映的名称。但
我试图将一个对象转换为json格式,但它不起作用(我得到一个奇怪的堆栈溢出异常)。它从对象到XML都能完美地工作。我有一个简单的实体类User和另一个具有多个关系的类。 相关类 我将@XmlTransient注释放在我想要忽略的getter上。 下面是我的rest服务中的一个方法,它从用户的昵称返回用户 因此,它使用@products({“application/xml”})而不是@product
你好,我有以下任务: 具有JSON对象的URL: *通过注释定义如何将JSON定义到Java列表中,并找到其中有“名称”的对象。 我认为问题是在不使用任何java库的情况下解析JSON。到目前为止,我已经开发了以下代码: 我在这里做的是我有一个JSONObject类,它将JSON属性存储在映射中,然后我想使用反射来填充任何类。 为了解析JSON,我尝试创建一个迷你FSM(:)),它使用For循环解
这里是我被困的地方,我在哪里创建我的新Gson()来在发送数据之前解析它?
问题内容: 我想使用google-gson将json数据解析为java对象。 这是我要解析的数据的示例: IsBean.java User.java RequestObj.java Test.java 错误: 问题答案: 如果没有看到的代码,我不能肯定的说,但是我很有把握地猜测该类有一个类型的字段,您可以使用它来容纳。如果是这样,那么问题在于GSON会扫描该类对象的字段,并且基于字段定义,必须创建
问题内容: 我在MongoDB中的规范化数据模型结构中遇到以下错误: 这是由于以下原因造成的: 具体的部分。我的文档中有一个DBRef对象,因此我可以引用另一个集合中的文档。嵌入式文档结构不是选项。那么我该如何解决呢? 问题答案: 您必须为其导入DBRef编解码器才能进行打印,如果您希望以文档json样式进行打印,则需要编写自己的DBRef编解码器,并将其添加到您给toJson()的编解码器中。
问题内容: 我有一个XML文件,例如 如何将其解析为JSON结构文件? 问题答案: 对于一个简单的解决方案,我建议使用Jackson库,它是一个Java库,用于生成和读取带有XML扩展名的JSON,因为它只需几行简单的代码就可以将任意复杂的XML转换为JSON。 input.xml Java代码: 该演示使用Jackson 1.7.7 (较新的1.7.8也可以使用),Jackson XML Dat
问题内容: 我创建了以下脚本,以便从Oracle SQL Developer从Mobile App DB(基于MongoDB)读取数据: 响应 (l_response_text) 是类似JSON的字符串。例如: 该代码可以正常工作,并将响应插入一个名为 appery的列表中 。但是,我需要解析此响应,以便每个数组进入名为 appery_test 的表中的特定列。表 appery_test 的列数与