【问题标题】:JSON to object issue with Jersey and GensonJSON 反对 Jersey 和 Genson 的问题
【发布时间】:2015-01-27 14:49:44
【问题描述】:

我在尝试使用 Jersey 和 Genson 执行 POST 调用时遇到以下问题:

.... com.owlike.genson.JsonBindingException:没有为类型接口 Animal 找到构造函数 ....

我有以下设置:

-> Animal.java

package com.test;

import org.codehaus.jackson.annotate.JsonSubTypes;
import org.codehaus.jackson.annotate.JsonTypeInfo;

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes( {@JsonSubTypes.Type(value = Dog.class, name = "dog") })
public interface Animal
{  }

-> Dog.java

package com.test;

import org.codehaus.jackson.annotate.JsonTypeName;
import org.codehaus.jackson.annotate.JsonProperty;

@JsonTypeName("dog")
public class Dog implements Animal
{
   @JsonProperty
   public String name;

   public String getName() { return name; }
   public void setName(String n) { this.name = n; }
}

-> Zoo.java

package com.test;

import java.util.List;

public class Zoo
{
   private List<Animal> animals;
   public List<Animal> getAnimals()
   {
     return animals;
   }

   public void setAnimals(List<Animal> animals)
   {
    this.animals = animals;
    } 
 }

-> GensonCustomResolver.java

package com.test;
import javax.ws.rs.next.ContextResolver;
import javax.ws.rs.next.Provider;

import com.owlike.genson.Genson;

@Provider
public class GensonCustomResolver implements ContextResolver<Genson>
{
   private final Genson genson = new      Genson.Builder().useRuntimeType(true).useClassMetadata(true).create();

   @Override
   public Genson getContext(Class<?> arg0)
   {
     return genson;
   }
}

-> JerseyService.java

package com.test;

import javax.ws.rs.*;
import org.codehaus.jackson.*;

@Path("/exampleservice")
public class JerseyService 
{


   @POST
   @Path("somePath")
   @Consumer(MediaType.APPLICATION_JSON)
   @Produces(MediaType.APPLICATION_JSON)
   public Zoo createAnotherZoo(Zoo zoo) throws JsonParseException, JsonMappingException, Exception
   {
      Zoo newZoo = new Zoo();
      Collection<Animal> animals = zoo.getAnimals();
      List<Animal> newAnimals = new ArrayList<Animal>();

      for (Animal a : animals) {
          Dog dog_a = (Dog) a;
          Dog dog_b = new Dog();
          dog_b.setName(dog_a.getName() + "TEST");
          newAnimals.add(dog_b);
      }
      newZoo.add(newAnimals);
      return newZoo;
   }
}

输入的 JSON 如下所示:

{
   "animals" : [
     {
       "name": "Unno"
     }
    ]
}

总而言之,我有一个 List,并且在反序列化我的对象时尝试使用其中一种接口实现。

提前谢谢你。

::::解决方案:::::

万一有人遇到这种情况:

我按照下面的建议完全删除了 genson 依赖项。只使用杰克逊注释,它似乎工作。我还从 Dog.java 的 name 属性中删除了 @JsonProperty。

谢谢你:) :)

【问题讨论】:

    标签: java jersey genson


    【解决方案1】:

    我认为您的意思是“我在反序列化我的对象时尝试使用其中一种接口实现。”

    你的问题

    如果这是你的意思,那么简短的回答是它不能那样工作。

    1. 我看到您正在使用 Jackson 注释,Genson 没有看到/使用这些注释(jackson 和 genson 是两个不同的库)。

    2. 基于 json 流(您提供的示例输入),Genson 无法知道要绑定哪个具体类


    一些可能的解决方案是

    • 如果您在两端使用相同的 pojos(动物、狗等)和 Genson(将数据发布到服务器和服务器的代码),则使用启用了 useRuntimeType 和 useClassMetadata 的 Genson 实例 两端应该工作。这将是最简单的解决方案。

      • 类元数据机制,在序列化期间将具体类型的类名写入json对象作为第一个条目,在反序列化期间,Genson 查找带有键@class 的第一个属性以提取具体的类名。 在您的情况下,如果您能够生成 {"animals":{"@class": "com.test.Dog", "name": "Unno"}} 形式的 json,那么 genson 会将其提供给正确的类型。请注意,您还可以为类型注册别名,因此您可以只写 dog 而不是完整的类名。 the documentation 了解更多详情。

      • 1234563注释)。在这种情况下,您不应该使用 Genson 来处理带有 jersey 的 ser/de,因为 jackson 和 genson 都做同样的工作。

    【讨论】:

    • 谢谢欧根。我的意思是反序列化,我已经更正了。我宁愿只和杰克逊呆在一起。现在我将删除 Genson 的东西,并尝试使用 jackson。 JSON 会是什么样子,你能评论一下吗?
    • 我猜它应该包含一些名为“type”的属性,并具有值“dog”。类似于 genson 中 @class 的行为,只是顺序可能无关紧要。
    • 你的意思是:{ "animals" : [ { "type" : "dog", "name": "Unno" } ] }
    • 是的,我认为您在 JsonTypeInfo 中设置了 property="type"。您可能还想阅读关于这些注释的 jacksons 文档,因为我不能 100% 确定其含义。
    • eugen,那是“几乎”工作。现在我收到了回复,但是回复看起来像这样:{"animals"{{"type":"dog","name":null}} 即使我在输入 json 中传递了名称。关于这个有什么想法吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-22
    • 1970-01-01
    • 2012-05-01
    相关资源
    最近更新 更多