gpt4 book ai didi

java - JsonNode 实例何时为 null?

转载 作者:行者123 更新时间:2023-12-02 11:57:31 25 4
gpt4 key购买 nike

考虑以下 Java 类定义。

CrudOperation.java:

package com.cyberfront.test.json.nll.demonstration;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.JsonNode;

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class CrudOperation{
public enum Type {CREATE,UPDATE,DELETE,READ}
private final Type type;
private final JsonNode op;

public CrudOperation(Type type) { this(type, null); }
public CrudOperation(JsonNode op) { this(Type.UPDATE, op); }

@JsonCreator
public CrudOperation(@JsonProperty("type") Type type, @JsonProperty("op") JsonNode op) {
this.type = type;
this.op = op;

boolean isUpdate = Type.UPDATE.equals(this.getType());
boolean isNotNull = null == this.getOp();
boolean isValid = isUpdate ^ isNotNull;

if (!isValid) {
System.out.println(" isUpdate: " + String.valueOf(isUpdate));
System.out.println("isNotNull: " + String.valueOf(isNotNull));
System.out.println(" isValid: " + String.valueOf(isValid));

throw new IllegalArgumentException("Operation Failed Validation: " + this.toString());
}
}

@JsonProperty("type")
public Type getType() { return this.type; };

@JsonProperty("op")
public JsonNode getOp() { return this.op; }

public static <T> String nullCheck(T val) { return null == val ? "null" : val.toString(); }

public static String toString(Type type, JsonNode op) {
return "{\"type\":\"" + nullCheck(type) + "\",\"op\":" + nullCheck(op) + "}";
}

@Override
public String toString() { return toString(this.getType(), this.getOp()); }
}

在此类中,带有 @JsonCreator 注释的构造函数执行验证,以确保在以下情况下存在非空 JsonNode 参数 op type 参数的值为 Type.UPDATE。也就是说,当 type 的值为 Type.UPDATE 时,op 应该为非空。如果 type 具有任何其他值,则 op 应为 null。

接下来考虑下面的类。

Main.java:

package com.cyberfront.test.json.nll.demonstration;

import com.cyberfront.test.json.nll.demonstration.CrudOperation.Type;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

public class Main {

private static ObjectMapper mapper = new ObjectMapper();

public static void main(String[] args) {
CrudOperation createObject = new CrudOperation(Type.CREATE);
System.out.println("Initial value: " + createObject.toString());

JsonNode createDocument = mapper.valueToTree(createObject);
System.out.println("Document value: " + createDocument.toString());

CrudOperation reconstructedObject = null;
try {
reconstructedObject = mapper.treeToValue(createDocument, CrudOperation.class);
} catch (JsonProcessingException e) {
System.out.println(e);
}

System.out.println("Reconstructed: " + CrudOperation.nullCheck(reconstructedObject));
}
}

这用于测试操作类型值为 Type.CREATECrudOperation 实例的创建,这意味着 op 应该为 null 。然而,这会产生以下输出:

Initial value: {"type":"CREATE","op":null}
Document value: {"@type":"CrudOperation","type":"CREATE"}
isUpdate: false
isNotNull: false
isValid: false
com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of com.cyberfront.test.json.nll.demonstration.CrudOperation, problem: Operation Failed Validation: {"type":"CREATE","op":null}
at [Source: N/A; line: -1, column: -1]
Reconstructed: null

初始 CrudOperation 实例化已验证,并且该实例到 JsonNode 实例的转换也可以正常工作。当尝试从原始派生的 JsonNode 重建 CrudOperation 实例时,会出现此问题。由于某种原因,op 的值显示为 null,但与 null 相等的测试失败,这又导致 CrudOperation 验证失败失败。

为什么会发生这种情况以及如何解决?

最佳答案

问题在于在此上下文中 null 的含义。在有问题的情况下,显然 op 已被实例化,因此不是 null。这可以通过在执行验证的构造函数中添加另一个输出行来显示:

System.out.println("    class:" + (null == op ? "Real Null" : op.getClass().toString()));

当程序再次运行时,会产生以下输出:

Initial value: {"type":"CREATE","op":null}
Document value: {"@type":"CrudOperation","type":"CREATE"}
isUpdate: false
isNotNull: false
isValid: false
class:class com.fasterxml.jackson.databind.node.NullNode
com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of com.cyberfront.test.json.nll.demonstration.CrudOperation, problem: Operation Failed Validation: {"type":"CREATE","op":null}
at [Source: N/A; line: -1, column: -1]
Reconstructed: null

也就是说,op 被实例化为 NullNode 对象类型,当对其执行 toString() 方法时,返回null 作为字符串而不是类型。

解决此问题的一个解决方案是使用 JsonNode.isNull() 方法来检测何时出现这种情况。

@JsonCreator
public CrudOperation(@JsonProperty("type") Type type, @JsonProperty("op") JsonNode op) {
this.type = type;
this.op = null == op || op.isNull() ? null : op;

boolean isUpdate = Type.UPDATE.equals(this.getType());
boolean isNotNull = null == this.getOp();
boolean isValid = isUpdate ^ isNotNull;

if (!isValid) {
System.out.println(" isUpdate: " + String.valueOf(isUpdate));
System.out.println("isNotNull: " + String.valueOf(isNotNull));
System.out.println(" isValid: " + String.valueOf(isValid));
System.out.println(" class:" + (null == op ? "Real Null" : op.getClass().toString()));

throw new IllegalArgumentException("Operation Failed Validation: " + this.toString());
}
}

isNull() 的额外检查将过滤掉 JsonNode 是实例化 null 节点的情况,并提供

Initial value: {"type":"CREATE","op":null}
Document value: {"@type":"CrudOperation","type":"CREATE"}
Reconstructed: {"type":"CREATE","op":null}

这达到了预期的结果。

关于java - JsonNode 实例何时为 null?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47483118/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com