MessageBodyWriter not found for media type=application/json when returning JSON in REST web service with Jersey

后端 未结 5 1602
难免孤独
难免孤独 2020-12-19 16:20

I am trying to create a very simple REST service using Jersey. Here is the service code

@Path(\"/UserService\")
publ         


        
5条回答
  •  轮回少年
    2020-12-19 16:26

    I am a bit upset about JAXB binding as well at the moment, therefore let me summarize my findings here - please correct me if I say something stupid:

    1. Of course you have to have a library to do the JSON (de)serialization, in my case it is Moxy.
    2. You have to tell JAXB which classes it should support. There are multiple ways to do that, the simplest seems to be to add a jaxb.properties file in the directory matching your classes and its sole content is the text javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory. With the directory I mean, if your classes are in the directory src/main/java and there the package com.pkg1.entities, add this file in src/main/resources and there as com/pkg1/entities/jaxb.properties.
    3. By default JAXB works on POJOs. So you need to have a constructor without arguments, a get- and a set-method. Only then this field will be present in the JSON.
    4. What I do often is to add a second constructor that gets the runtime object passed in and sets all fields to be exposed directly. Hence I do not need and do not want a set-method. Solution is to annotate the get method with @XmlElement.
    5. Did I say you need an empty/default constructor? Took me once three hours to find out why class1 was working fine, class2 got the MessageBodyWriter error. I had forgotten the constructor. Grrrrr.
    6. You get the same error (I believe) when the class is configured fine but one of its fields returns a type it cannot serialize.
    7. I believe to have had one case where the class annotation @XmlRootElement caused that error. Not sure but I barely use that annotation at the moment.
    8. In case you have a List as one of the elements to be turned into a Json array, JAXB will use the myAbstract class to do the serialization. Not very useful, you want the actual objects to be serialized. But how should JAXB know who implemented/extended this class? You have to tell with the annotation @XmlSeeAlso. So the MyAbstract class gets a class annotation @XmlSeeAlso({MyConcrete1.class, MyConcrete2.class}). At least Moxy does add then an additional type field telling the consumer which class it was. Makes total sense.
    9. Although you can return userList the better option would be to return Response.ok().entity(userList).build(); Then you can return errors as well. Logically it is the same.
    10. Watchout what kind of data types you use. String is fine, ArrayList as well, Hashtable not. Depends on the serializer you use as well.

    I hope this helps others.

提交回复
热议问题