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

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

Deserialize String as List of Strings

问题

  1. 我有一个POJO包含以下属性
  2. public class Example {
  3. @JsonProperty("inputFoo")
  4. private String foo;
  5. @JsonProperty("inputBar")
  6. private String bar;
  7. @JsonProperty("inputBaz")
  8. @JsonDeserialize(using = MyDeserializer.class)
  9. private Set<String> baz;
  10. }
  11. 我正在处理的JSON目前将baz属性表示为单个字符串
  12. {"inputFoo":"a", "inputBar":"b", "inputBaz":"c"}
  13. 我正在使用Jackson ObjectMapper尝试将JSON转换为我的POJO我知道JSON中的input baz字符串无法直接映射到我尝试表示的Set因此我定义了一个自定义的Deserializer
  14. public class MyDeserializer extends StdDeserializer<Set<String>> {
  15. public MyDeserializer() {
  16. super((Class<?>) null);
  17. }
  18. public Set<String> deserialize(JsonParser p, DeserializationContext cxt) throws IOException, JsonProcessingException {
  19. String input = p.readValueAs(String.class);
  20. Set<String> output = new HashSet<>();
  21. if(input != null) {
  22. output.add(input);
  23. }
  24. return output;
  25. }
  26. }
  27. 关于"inputBaz"属性我遇到了一个IllegalArgumentException我可以提供详细信息有人看到我的Deserializer实现中是否有明显的问题吗谢谢
英文:

I have a POJO that contains the following attributes

  1. public class Example {
  2. @JsonProperty(&quot;inputFoo&quot;)
  3. private String foo
  4. @JsonProperty(&quot;inputBar&quot;)
  5. private String bar
  6. @JsonProperty(&quot;inputBaz&quot;)
  7. @JsonDeserialize(using = MyDeserializer.class)
  8. private Set&lt;String&gt; baz
  9. }

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

  1. {&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:

  1. public class MyDeserializer extends StdDeserializer&lt;Set&lt;String&gt;&gt; {
  2. public MyDeserializer(){}
  3. public MyDeserializer(Class&lt;?&gt; vc) {
  4. super(vc);
  5. }
  6. public Set&lt;String&gt; deserialize(JsonParser p, DeserializationContext cxt) throws IOException, JsonProcessingException {
  7. String input = p.readValueAs(String.class);
  8. Set&lt;String&gt; output = new HashSet&lt;&gt;();
  9. if(input != null) {
  10. output.add(input);
  11. }
  12. return output;
  13. }
  14. }

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

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

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

Replace the 2 constructors with this no-arg constructor:

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

答案3

得分: 0

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

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

  1. public class Example {
  2. @JsonCreator
  3. public Example(@JsonProperty("inputFoo") String foo,
  4. @JsonProperty("inputBar") String bar,
  5. @JsonProperty("inputBaz") String strBaz) {
  6. this.foo = foo;
  7. this.bar = bar;
  8. this.baz = new HashSet<>();
  9. baz.add(strBaz);
  10. }
  11. private String foo;
  12. private String bar;
  13. private Set<String> baz;
  14. }

只是为了展示在更一般的情况下,您可以避免使用 @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:

  1. public class Example {
  2. @JsonCreator
  3. public Example(@JsonProperty(&quot;inputFoo&quot;) String foo,
  4. @JsonProperty(&quot;inputBar&quot;) String bar,
  5. @JsonProperty(&quot;inputBaz&quot;) String strBaz) {
  6. this.foo = foo;
  7. this.bar = bar;
  8. this.baz = new HashSet&lt;&gt;();
  9. baz.add(strBaz);
  10. }
  11. private String foo;
  12. private String bar;
  13. private Set&lt;String&gt; baz;
  14. }

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:

确定