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

后端 未结 5 1600
难免孤独
难免孤独 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:24

    To use Jackson 2.x as your JSON provider you need to add jersey-media-json-jackson module to your pom.xml file:

    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-jackson</artifactId>
        <version>2.22.2</version>
    </dependency>
    

    And then register the JacksonFeature in your Application/ResourceConfig subclass.

    For more details, have a look at Jersey documentation.

    0 讨论(0)
  • 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.

    0 讨论(0)
  • 2020-12-19 16:28

    I tried a ton of these dependencies but none of them worked for my version of Jersey3. What I needed to do was turn the Arraylist into an actual array. I managed this with toArray() and it started serializing correctly!

    0 讨论(0)
  • 2020-12-19 16:36

    Your xml was working so I assume that you have @XmlRootElement annotation in your User class.

    The thing is, it knows how to convert it to xml with the annotation @XmlRootElement but it doesn't know how to convert it to JSON.

    So for making it convert everything to JSON with the same annotation of xml(ie @XmlRootElement) we can add

    jersey-media-moxy-<whatever version>.jar

    or for maven users

    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-moxy</artifactId>
    </dependency>
    

    Also it should have a no argument constructor

    0 讨论(0)
  • 2020-12-19 16:47

    You need a json serializer on your class path to make this work.

    Just add jackson and jersey will use this in the writer. E.g. if you are using maven, add this to the pom.xml

    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.7.4</version>
    </dependency>
    
    0 讨论(0)
提交回复
热议问题