【问题标题】:jackson deserialize unknown property name to custom entity杰克逊将未知属性名称反序列化为自定义实体
【发布时间】:2016-04-03 19:48:07
【问题描述】:

我正在尝试使用jackson 反序列化一个yaml 文件,它的工作方式类似于Json,所以为了方便我将使用Json。

我的 Json 结构如下所示:

 {
    "version": "2",
    "services": {
        "app": {
            "build": {
                "context": "./",
                "args": {}
            },
            "image": "imageName"
        },
        "results": {
            "build": "./",
            "image": "imageName"
        }
    }
}    

我想使用 jackson 对其进行反序列化,但在使用默认 ObjectMapper 时出现 UnknownPropertyException。

这是我要反序列化的类:

public class ServiceModel {

List<ContainerModel> containers;

public List<ContainerModel> getContainers() {
    return containers;
}

public void setContainers(List<ContainerModel> containers) {
    this.containers = containers;
}
}

我的容器模型看起来像这样:

public class ContainerModel {

@JsonProperty("build")
private String build;

@JsonProperty("args")
private List<String> args;

@JsonProperty("context")
private String context;

@JsonProperty("dockerfile")
private String dockerFile;

// Getters and Setters below

编辑:我在描述 Json 结构时是错误的。请查看我将jackson映射到JsonNode时生成的更正的Json结构

这里应该把app和results映射到ContainerModel

【问题讨论】:

  • 您能提供(部分)您要反序列化的类吗?
  • @nyname00 请查看编辑。谢谢
  • @r0shi,你也可以发ContainerModel吗?
  • @Casey 添加了 ContainerModel。它没有任何自定义对象,并且属性名称也是已知的,所以我认为这不会是一个大问题
  • 我猜 'app' 中的 'build' 属性不应该包含 'context' 和 'args'。而且,您的班级中没有“图像”属性。应该是“dockerFile”吗?

标签: java json jackson deserialization


【解决方案1】:

编辑

查看您的新 Json 结构,ServiceModel 类应如下所示:

public class ServiceModel {
    private String version;
    private Map<String, ContainerModel> containers;
    // Other fields here...

    public void setContainers(Map<String, ContainerModel> containers) {
        this.containers = containers;
    }

    public Map<String, ContainerModel> getContainers() {
        return containers;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    public String getVersion() {
        return version;
    }

    // Other setters/getters here...
}

通过这种方式,您可以获得从键(字符串)到 ContainerModel 的映射。

原帖

嗯,您的 Json 示例有一个名为 services 的属性,而您的类有一个名为 containers 的属性。您不应该期望这些属性之间会自动映射。

要自动映射它们,请使用相同的属性名称。如果您不想或不能,您可以随时使用 Jackson 的注解 @JsonProperty。 此外,如果有您不想映射的字段,您应该实例化一个新的 ObjectMapper,并将其配置为忽略未知字段。像这样:

ObjectMapper objectMapper = new ObjectMapper(); 
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

另外,我假设您得到了映射 ServiceModel 类的异常,而不是 //Known data structure。但无论如何,我的建议应该可以解决这两种情况。

【讨论】:

  • 我有一个服务包装器,它也映射了 ServiceModel,所以我认为这不是问题。将var1映射到ContainerModel时出现问题
  • 啊!我懂了。那么你的结构对我来说似乎并不准确。它应该是这样的:“服务”:[{ContainerModel element here},{another ContainerModel element here}]
  • 是的,但是如果我不知道密钥,我该如何映射它(并且它被设计为有任何密钥)
  • 那么,像您在 ServiceModel 类中的列表不是正确的结构。我猜你想要的是一张地图? Map&lt;String, ContainerModel&gt; 也许?
  • 这解决了我在获取 ContainerModel 实例时遇到的问题。现在的问题是如何绑定可以是字符串或字典的构建。编辑:我想我可能需要为它编写一个自定义序列化程序
【解决方案2】:

您似乎正在尝试反序列化一个不存在的属性。

默认情况下,当您尝试反序列化未知属性时,Jackson 会抛出异常。您可以通过将以下内容添加到您的 ObjectMapper 实例来禁用此功能:

objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);

不过,您可能希望修复未知属性。它很可能是您在 Java 类中声明为 containersservices 属性。

【讨论】:

  • 嗯,容器属性存在,只是它的名字未知
  • 数组servicesServiceModel 实例的列表还是ContainerModel 实例的列表?
  • 服务数组是 ContainerModel 实例的列表,尽管如果需要,我可以完全消除 ServiceModel 并在当前存储服务数组的包装模型中使用 List。我基本上是在为 docker-compose.yml 编写一个解析器,如果你对此很熟悉并且想要对结构有一个完整的参考
  • 看看最后的编辑,我相信这会解决你的问题。
  • 抱歉造成混乱,请查看编辑。现在应该更清楚一点了。
猜你喜欢
  • 1970-01-01
  • 2017-01-30
  • 2013-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-22
  • 2023-04-07
  • 2017-09-02
相关资源
最近更新 更多