反序列化字符串为字符串列表

huangapple go评论79阅读模式
英文:

Deserialize String as List of Strings

问题

我有一个POJO包含以下属性

public class Example {
  @JsonProperty("inputFoo")
  private String foo;
  @JsonProperty("inputBar")
  private String bar;
  @JsonProperty("inputBaz")
  @JsonDeserialize(using = MyDeserializer.class)
  private Set<String> baz;
}

我正在处理的JSON目前将baz属性表示为单个字符串

{"inputFoo":"a", "inputBar":"b", "inputBaz":"c"}

我正在使用Jackson ObjectMapper尝试将JSON转换为我的POJO我知道JSON中的input baz字符串无法直接映射到我尝试表示的Set因此我定义了一个自定义的Deserializer

public class MyDeserializer extends StdDeserializer<Set<String>> {
   public MyDeserializer() {
       super((Class<?>) null);
   }

   public Set<String> deserialize(JsonParser p, DeserializationContext cxt) throws IOException, JsonProcessingException {
      String input = p.readValueAs(String.class);
      Set<String> output = new HashSet<>();
      if(input != null) {
         output.add(input);
      }
      return output;
   }
}

关于"inputBaz"属性我遇到了一个IllegalArgumentException我可以提供详细信息有人看到我的Deserializer实现中是否有明显的问题吗谢谢
英文:

I have a POJO that contains the following attributes

public class Example {
  @JsonProperty(&quot;inputFoo&quot;)
  private String foo
  @JsonProperty(&quot;inputBar&quot;)
  private String bar
  @JsonProperty(&quot;inputBaz&quot;)
  @JsonDeserialize(using = MyDeserializer.class)
  private Set&lt;String&gt; baz
}

The JSON that I am working with to represent this data currently represents the baz attribute as a single string:

{&quot;inputFoo&quot;:&quot;a&quot;, &quot;inputBar&quot;:&quot;b&quot;, &quot;inputBaz&quot;:&quot;c&quot;}

I am using the Jackson ObjectMapper to attempt to convert the JSON to my POJO. I know that the input baz String from the JSON wont map cleanly to the Set that I am trying to represent it as, so I defined a custom Deserializer:

public class MyDeserializer extends StdDeserializer&lt;Set&lt;String&gt;&gt; {
   public MyDeserializer(){}

   public MyDeserializer(Class&lt;?&gt; vc) {
      super(vc);
   }

   public Set&lt;String&gt; deserialize(JsonParser p, DeserializationContext cxt) throws IOException, JsonProcessingException {
      String input = p.readValueAs(String.class);
      Set&lt;String&gt; output = new HashSet&lt;&gt;();
      if(input != null) {
         output.add(input);
      }
      return output;
   }
}

I am getting an IllegalArgumentException referencing the "inputBaz" attribute, which I can provide details on. Does anyone see any obvious issue with my deserializer implementation? Thanks

答案1

得分: 2

不需要实现自定义反序列化器,使用ACCEPT_SINGLE_VALUE_AS_ARRAY功能。它也适用于集合:

> 该功能确定是否可以将非数组(在JSON中)的值强制转换为与Java集合(数组,java.util.Collection)类型一起使用。如果启用,集合反序列化器将尝试处理非数组值,就好像它们有一个“隐式”包围的JSON数组。此功能旨在用于兼容性/互操作性的原因,以便与在某些情况下在数组中只有单个元素的情况下,会在JSON数组中省略数组的软件包(例如XML到JSON转换器)一起使用。默认情况下,禁用此功能。

另请参阅:

英文:

You do not need to implement custom deserialiser, use ACCEPT_SINGLE_VALUE_AS_ARRAY feature. It works for sets as well:

> Feature that determines whether it is acceptable to coerce non-array
> (in JSON) values to work with Java collection (arrays,
> java.util.Collection) types
. If enabled, collection deserializers will
> try to handle non-array values as if they had "implicit" surrounding
> JSON array. This feature is meant to be used for
> compatibility/interoperability reasons, to work with packages (such as
> XML-to-JSON converters) that leave out JSON array in cases where there
> is just a single element in array. Feature is disabled by default.

See also:

答案2

得分: 0

用这个无参构造函数替换掉这两个构造函数:

public MyDeserializer() {
	super(TypeFactory.defaultInstance().constructCollectionType(Set.class, String.class));
}
英文:

Replace the 2 constructors with this no-arg constructor:

public MyDeserializer() {
	super(TypeFactory.defaultInstance().constructCollectionType(Set.class, String.class));
}

答案3

得分: 0

ACCEPT_SINGLE_VALUE_AS_ARRAY 作为建议的选项是一个不错的选择。

也许您实际的问题更加复杂,但如果不是的话,您也可以尝试使用 @JsonCreator 替代自定义的反序列化程序。就像这样:

public class Example {

    @JsonCreator
    public Example(@JsonProperty("inputFoo") String foo,
            @JsonProperty("inputBar") String bar,
            @JsonProperty("inputBaz") String strBaz) {
        this.foo = foo;
        this.bar = bar;
        this.baz = new HashSet<>();
        baz.add(strBaz);
    }

    private String foo;
    private String bar;
    private Set<String> baz;
}

只是为了展示在更一般的情况下,您可以避免使用 @JsonCreator 来实现自定义的反序列化程序,但仍然可以进行一些简单的转换。

英文:

ACCEPT_SINGLE_VALUE_AS_ARRAY as suggested is a good option.

Maybe your actual problem is more complicated but if not you could also try @JsonCreator instead of custom deserializer. Like:

public class Example {

	@JsonCreator
	public Example(@JsonProperty(&quot;inputFoo&quot;) String foo,
			@JsonProperty(&quot;inputBar&quot;) String bar,
			@JsonProperty(&quot;inputBaz&quot;) String strBaz) {
		this.foo = foo;
		this.bar = bar;
		this.baz = new HashSet&lt;&gt;();
		baz.add(strBaz);
	}

	private String foo;
	private String bar;
	private Set&lt;String&gt; baz;
}

Just to show that in more general case you might avoid implementing custom deserializer with @JsonCreator also but still make some simple conversions.

huangapple
  • 本文由 发表于 2020年9月22日 23:57:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/64013438.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定