【问题标题】:Java REST service JSON parsing inconsistent with unit test parsing?Java REST服务JSON解析与单元测试解析不一致?
【发布时间】:2015-11-03 15:11:31
【问题描述】:

我有一个问题,我在 Glassfish 上部署了一个 Web 服务,但它没有反序列化 POST 数据以正确添加一个人。

当我在测试用例中序列化/反序列化时,它工作正常。如何让 GF 像我的测试用例一样使用 ObjectMapper?我的 bean 以及适用于我的测试用例但在发布到 REST 服务时不起作用的 JSON。

public class PhoneNumber implements Serializable {
    String countryCode;
    String areaCode;
    String subscriberNubmer;
    String extension;

    public PhoneNumber() {
        super();
    }

    /**
     * @param countryCode
     * @param areaCode
     * @param subscriberNubmer
     * @param extension
     */
    public PhoneNumber(String countryCode, String areaCode, String subscriberNubmer,
            String extension) {
        super();
        this.countryCode = countryCode;
        this.areaCode = areaCode;
        this.subscriberNubmer = subscriberNubmer;
        this.extension = extension;
    }
    ... getters and other stuff ...
}   

@Entity
@Table(name = "ent_person")
public class Person implements Serializable, Comparable<Person> {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    /**
     * Comment for <code>serialVersionUID</code>
     */
    private static final long serialVersionUID = -4680156785318108346L;

    protected String firstName;

    protected String nickname;

    protected String lastName;

    @ElementCollection(fetch = FetchType.EAGER)
    protected List<String> middleNames;

    protected String idNum;

    protected char isMale;

    @Temporal(value = TemporalType.DATE)
    protected Date birthday;

    @ElementCollection(fetch = FetchType.EAGER)
    @MapKeyColumn(name = "name")
    @Column(name = "value")
    protected Map<String, PhoneNumber> phoneNumbers;

    public Person() {
        super();
    }

    /**
     * @param firstName
     * @param nickname
     * @param lastName
     * @param middleNames
     * @param idNum
     * @param isMale
     * @param birthday
     */
    public Person(String firstName, String nickname, String lastName, List<String> middleNames,
            String idNum, char isMale, Date birthday, Map<String, PhoneNumber> phoneNumbers) {
        super();
        this.firstName = firstName;
        this.nickname = nickname;
        this.lastName = lastName;
        this.middleNames = middleNames;
        this.idNum = idNum;
        this.isMale = isMale;
        this.birthday = birthday;
        this.phoneNumbers = phoneNumbers;
    }
    ... getters and setters ...
}

这是由测试用例序列化方法生成的 JSON 数据,并且在带有 ObjectMapper 的测试用例中正确反序列化。但是,它不能在 Web 应用程序中正确反序列化。

{
    "id": null,
    "firstName": "John",
    "nickname": "JJ",
    "lastName": "Smith",
    "middleNames": [
        "Stelling",
        "Deering"
    ],
    "idNum": "js3234",
    "isMale": "n",
    "birthday": 778266673889,
    "phoneNumbers": {
        "Personal Mobile": {
            "countryCode": "26",
            "areaCode": "200",
            "subscriberNubmer": "4069942",
            "extension": null
        },
        "Home": {
            "countryCode": "79",
            "areaCode": "115",
            "subscriberNubmer": "9518863",
            "extension": null
        }
    }
}

这是我发布上述 JSON 时 Web 服务提供给我的内容。请注意,phoneNumbers 映射只有 1 个键“条目”并且没有值???

{"firstName":"John","id":1,"idNum":"js3234","isMale":"n","lastName":"Smith","middleNames":["Stelling","Deering"],"nickname":"JJ","phoneNumbers":{"entry":[]}}

这是测试用例,效果很好,上面的 JSON 就是这个用例生成的(val 字符串)

@Test
public void testSimpleSerializeToFromJson() throws IOException {
    int phoneNumberCount;
    Person p;

    p = BeanFactory.getDummyPerson();
    assertNotNull(p.getPhoneNumbers());
    phoneNumberCount = p.getPhoneNumbers().size();
    assertTrue(phoneNumberCount > 0);

    String val = mapper.writeValueAsString(p);
    assertNotNull(val);


    Person p2 = mapper.readValue(val, Person.class);
    System.out.println(p2.getPhoneNumbers());
    assertNotNull(p2.getPhoneNumbers());
    assertTrue(p2.getPhoneNumbers().size() == phoneNumberCount);
    assertFalse(p == p2);
    assertTrue(p2.equals(p));
}

【问题讨论】:

    标签: java json rest serialization


    【解决方案1】:

    好的,我终于找到了答案。地图不会根据this table自动反序列化

    我必须添加一个自定义 MessageBodyReader 来读取字符串。由于我已经有一个工作单元测试来读取字符串,所以添加正确的类和注释很简单,之后一切正常:

    @Consumes("application/json")
    @Provider
    public class PersonReader 
     implements MessageBodyReader<Person> {
        ObjectMapper mapper;
    
        public PersonReader(){
            mapper = new ObjectMapper();
        }
    
        public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
            return type == Person.class;
        }
    
        public Person readFrom(Class<Person> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException, WebApplicationException {
            Person p = mapper.readValue(entityStream, Person.class);
            return p;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-18
      • 2023-03-12
      • 2013-05-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多