How to reuse Jersey's JSON/JAXB for serialization?

前端 未结 7 1319
失恋的感觉
失恋的感觉 2020-11-29 23:48

I have a JAX-RS REST service implemented using Jersey. One of the cool features of JAX-RS/Jersey is how easily a POJO can be turned into a REST service, simply by sprinkling

相关标签:
7条回答
  • 2020-11-30 00:30

    I understand XML views but it would have shown some foresight to require JSON support for POJOs as standard equipment. Having to doctor up JSON identifiers with special characters makes no sense if your implementation is JSON and your client is a JavaScript RIA.

    Also, not that Java Beans are NOT POJOs. I would like to use something like this on the outer surface of my web tier:

    public class Model
    {
       @Property height;
       @Property weight;
       @Property age;
    }
    

    No default constructor, no getter/setter noise, just a POJO with my own annotations.

    0 讨论(0)
  • 2020-11-30 00:38

    Since Jersey is a reference implementation of JAX-RS and JAX-RS is focused completely on providing a standard way of implementing the end-point for the REST service the issues of serializing the payload is left to other standards.

    I think that if they included object serialization in the JAX-RS standard it would quickly become a large multi-headed beast that would be difficult to implement and loose some of it's focus.

    I appreciate how focused Jersey is on delivering clean and simple to use REST endpoints. In my case I've just subclassed a parent that has all the JAXB plumbing in it so marshalling objects between binary and XML is very clean.

    0 讨论(0)
  • 2020-11-30 00:39
    ObjectMapper mapper = new ObjectMapper();
    String str = mapper.writeValueAsString(pojoObject);
    
    0 讨论(0)
  • 2020-11-30 00:40

    With a little Jersey specific bootstrapping, you can use it to create the necessary JSON objects for you. You need to include the following dependencies (you can use bundle, but it will cause problems if you are using Weld for testing):

        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-json</artifactId>
            <version>1.12</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-client</artifactId>
            <version>1.12</version>
        </dependency>
    

    From there you can create a JAXB annotated class. The following is an example:

    @XmlRootElement
    public class TextMessage {
    private String text;
        public String getText() { return text; }
        public void setText(String s) { this.text = text; }
    }
    

    Then you can create the following unit test:

        TextMessage textMessage = new TextMessage();
        textMessage.setText("hello");
        textMessage.setUuid(UUID.randomUUID());
    
        // Jersey specific start
        final Providers ps = new Client().getProviders();
        // Jersey specific end
        final MultivaluedMap<String, Object> responseHeaders = new MultivaluedMap<String, Object>() {
    
            @Override
            public void add(final String key, final Object value) {
            }
    
            @Override
            public void clear() {
            }
    
            @Override
            public boolean containsKey(final Object key) {
                return false;
            }
    
            @Override
            public boolean containsValue(final Object value) {
                return false;
            }
    
            @Override
            public Set<java.util.Map.Entry<String, List<Object>>> entrySet() {
                return null;
            }
    
            @Override
            public List<Object> get(final Object key) {
                return null;
            }
    
            @Override
            public Object getFirst(final String key) {
                return null;
            }
    
            @Override
            public boolean isEmpty() {
                return false;
            }
    
            @Override
            public Set<String> keySet() {
                return null;
            }
    
            @Override
            public List<Object> put(final String key, final List<Object> value) {
                return null;
            }
    
            @Override
            public void putAll(
                    final Map<? extends String, ? extends List<Object>> m) {
            }
    
            @Override
            public void putSingle(final String key, final Object value) {
            }
    
            @Override
            public List<Object> remove(final Object key) {
                return null;
            }
    
            @Override
            public int size() {
                return 0;
            }
    
            @Override
            public Collection<List<Object>> values() {
                return null;
            }
        };
    
        final MessageBodyWriter<TextMessage> messageBodyWriter = ps
                .getMessageBodyWriter(TextMessage.class, TextMessage.class,
                        new Annotation[0], MediaType.APPLICATION_JSON_TYPE);
        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
        Assert.assertNotNull(messageBodyWriter);
    
        messageBodyWriter.writeTo(textMessage, TextMessage.class,
                TextMessage.class, new Annotation[0],
                MediaType.APPLICATION_JSON_TYPE, responseHeaders, baos);
        final String jsonString = new String(baos.toByteArray());
        Assert.assertTrue(jsonString.contains("\"text\":\"hello\""));
    

    The advantage to this approach is it keeps everything within the JEE6 API, no external libraries are explicitly needed except for testing and getting the providers. However, you need to create an implementation of MultivaluedMap since there is nothing provided in the standard and we don't actually use it. It may also be slower than GSON, and a lot more complicated than necessary.

    0 讨论(0)
  • 2020-11-30 00:41

    Jersey uses a couple different frameworks depending on whether you use mapped(), badgerfish(), or natural() notation. Natural is usually the one people want. And that's implemented using the very good (and very fast) standalone Jackson JSON processor, I believe, which goes from Object->JAXB->JSON. However Jackson also provides it's own JAX-RS provider to go direct Object->JSON.

    In fact, they even added support for JAXB annotations. Have a look at

    http://wiki.fasterxml.com/JacksonJAXBAnnotations

    I think that's ultimately what you are looking for. Jackson does Object<->JSON processing...Jersey just makes the calls for you

    0 讨论(0)
  • 2020-11-30 00:46

    Here's a simple brief example of using JAXB to map objects to JSON (using Jackson):

    http://ondra.zizka.cz/stranky/programovani/java/jaxb-json-jackson-howto.texy

    0 讨论(0)
提交回复
热议问题