【问题标题】:Jax rs enum deserialization case insensitiveJax rs 枚举反序列化不区分大小写
【发布时间】:2018-04-16 12:34:07
【问题描述】:

我有一个使用 json 请求的 REST Web 服务:

@PUT
@Produces({ MediaType.APPLICATION_JSON })
@Consumes(value = { MediaType.APPLICATION_JSON })
public Response processRequest(Request request)

请求是更新列表:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
public class Request {
    @XmlElement
    private List<Update> update;
}

更新类有一个枚举字段:

@XmlAccessorType(XmlAccessType.FIELD)
public class Update implements Serializable {
    private static final long serialVersionUID = 1L;

    @XmlElement(name = "ID")
    private Integer id;

    @XmlElement(name = "Status")
    private Status status;
}

状态是一个枚举:

@XmlEnum
public enum Status  {
    @XmlEnumValue("active")
    ACTIVE("active"), 
    @XmlEnumValue("cancelled")
    CANCELLED("cancelled"); 
}

我希望将字符串“active”、“Active”、“ACTIVE”...反序列化为枚举 ACTIVE,但所有尝试均失败:Update java 对象中的状态字段为空(从 String 转换使用 Active 或 ACTIVE 输入字符串枚举失败)

我尝试创建一个自定义反序列化器,但不确定我做得是否好:

@Provider
public class IgnoreCaseDeserializer extends StdDeserializer<Status>{

    private static final long serialVersionUID = 1L;

    public IgnoreCaseDeserializer() {
        this(null);
    }

    protected IgnoreCaseDeserializer(Class<?> vc) {
        super(vc);
    }

    @Override
    public Status deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        return Status.fromString(jp.getValueAsString().toLowerCase());
    }
}

我添加了@JsonDeserialize 注释:

@JsonDeserialize(using=IgnoreCaseDeserializer.class)
@XmlEnum
public enum HopperStatus  

我做错了什么?

感谢您的帮助

【问题讨论】:

  • 您正在混合使用 JAXB 和 Jackson API。您的端点建议您期望 JSON 格式的请求和响应,但是您的请求和响应 bean 正在使用 JAXB (XML) API。
  • 我找不到执行此操作的 JAXB 方式,因此我尝试使用 jackson。我怎样才能只使用 JAXB?

标签: java jackson jax-rs


【解决方案1】:

建议优先。如果将 XML 元素和属性声明为大写,则最好将所有元素和属性声明为大写。所以

@XmlRootElement(name = "Request") public class Request

@XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(name = "Update") public class Update implements Serializable {

@XmlElement(name = "Updates") private List<Update> update;

对于原始类型和字符串,我们通常将它们声明为@XMLAttribute,对于类和枚举,我们将它们声明为@XMLElement。

并且您应该附加请求 XML 内容,这很重要。我根据您的定义创建它。

<Request>
  <Updates>
    <Update>
      <ID>1</ID>
      <Status>active</Status>
    </Update>
  </Updates>
</Request>

而对于active、ACTIVE或Active请求内容转换,我建议你使用XMLAdapter。

public class StatusAdapter extends XMLAdapter<String, Status> {
    @Override
    public Status unmarshal(String status) throws Exception {

        return Status.fromValue(status.toLowerCase()); /* ensure status is not 
           blank, or you should check null before toLowerCase(). Usually, `required` is
     set in XML annotations, eg @XMLAttribute(name = "name", required = true) */
    }

    @Override
    public String marshal(Status status) throws Exception {

        return status.value();
    }
}

并将适配器添加到您使用的状态。

@XmlElement(name = "Status", required = true)
@XMLJavaTypeAdapter(StatusAdapter.class)
private Status status;

【讨论】:

  • 感谢您的建议和 XMLAdapter:这正是我所需要的
猜你喜欢
  • 2012-02-22
  • 2023-01-18
  • 2015-10-27
  • 1970-01-01
  • 2020-03-28
  • 2016-07-14
  • 2021-08-16
  • 2016-04-06
相关资源
最近更新 更多