2016-08-30 1 views
1

Я работаю над встроенным экземпляром джерси, который будет запускать службу JAXB RESTful. Я настроил Джексон с двумя шагами:Джерси Джексон unmarshall JSON

  1. Добавление это мой POM

    <dependency> 
        <groupId>org.glassfish.jersey.media</groupId> 
        <artifactId>jersey-media-json-jackson</artifactId> 
        <version>2.23.2</version> 
    </dependency> 
    
  2. зарегистрировав его в моем приложении

    public HandheldApplication() { 
    scripts.add(HandheldServer.class); 
    scripts.add(BasicScript.class); 
    // Add JacksonFeature. 
    scripts.add(JacksonFeature.class); 
    scripts.add(LoggingFilter.class); 
    

    }

У меня есть передается сложный объект ba ск и вперед, как показано ниже:

package com.ziath.handheldserver.valueobjects; 

import java.util.ArrayList; 
import java.util.List; 

import javax.xml.bind.annotation.*; 

@SuppressWarnings("restriction") 
@XmlRootElement 
public class Widget { 

private String key; 
private String name; 
private List<String> options = new ArrayList<String>(); 
private String value; 
private String type; 

public Widget(){ 
    super(); 
} 

public Widget(String key, String name, List<String> options, String value, 
     String type) { 
    super(); 
    this.key = key; 
    this.name = name; 
    this.options = options; 
    this.value = value; 
    this.type = type; 
} 

public String getKey() { 
    return key; 
} 
public void setKey(String key) { 
    this.key = key; 
} 
public String getName() { 
    return name; 
} 
public void setName(String name) { 
    this.name = name; 
} 
public List<String> getOptions() { 
    return options; 
} 
public void setOptions(List<String> options) { 
    this.options = options; 
} 
public String getValue() { 
    return value; 
} 
public void setValue(String value) { 
    this.value = value; 
} 
public String getType() { 
    return type; 
} 
public void setType(String type) { 
    this.type = type; 
} 

}

Когда я выполнить это в методе GET, как показано ниже:

@Override 
@GET 
@Path("getKeys") 
@Produces(MediaType.APPLICATION_JSON) 
public List<Widget> getKeys(@QueryParam(value = "page") int page) 

Это прекрасно работает, и я получаю JSON обратно; Однако, когда я исполню это PUT, как показано ниже:

@Override 
@PUT 
@Path("validateKeys") 
@Produces({MediaType.APPLICATION_JSON}) 
@Consumes(MediaType.APPLICATION_JSON) 
public boolean validateKeys(@QueryParam(value = "page")int page, @QueryParam(value = "widgets")List<Widget> widgets) 

Когда я исполняю PUT для доступа этого метода я получаю трассировку стека следующим образом:

Caused by: org.glassfish.jersey.internal.inject.ExtractorException: Error un-marshalling JAXB object of type: class com.ziath.handheldserver.valueobjects.Widget. 
    at org.glassfish.jersey.jaxb.internal.JaxbStringReaderProvider$RootElementProvider$1.fromString(JaxbStringReaderProvider.java:195) 
    at org.glassfish.jersey.server.internal.inject.AbstractParamValueExtractor.convert(AbstractParamValueExtractor.java:139) 
    at org.glassfish.jersey.server.internal.inject.AbstractParamValueExtractor.fromString(AbstractParamValueExtractor.java:130) 
    at org.glassfish.jersey.server.internal.inject.CollectionExtractor.extract(CollectionExtractor.java:88) 
    at org.glassfish.jersey.server.internal.inject.CollectionExtractor$ListValueOf.extract(CollectionExtractor.java:107) 
    at org.glassfish.jersey.server.internal.inject.QueryParamValueFactoryProvider$QueryParamValueFactory.provide(QueryParamValueFactoryProvider.java:89) 
    ... 38 more 
Caused by: javax.xml.bind.UnmarshalException 
- with linked exception: 
[org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Content is not allowed in prolog.] 
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:335) 
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.createUnmarshalException(UnmarshallerImpl.java:563) 
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:249) 
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:214) 
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:140) 
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:123) 
    at org.glassfish.jersey.jaxb.internal.JaxbStringReaderProvider$RootElementProvider$1.fromString(JaxbStringReaderProvider.java:190) 
    ... 43 more 

Так что, мне кажется, что Джексон правильно marshalling мой POJO в JSON но пытается unmarshall это как XML. Обратите внимание, что я переключился на Джексона от MOXy, потому что мне нужно было обрабатывать коллекции, возвращающиеся туда и обратно, и, судя по всему, MOXy не может этого сделать.

Есть ли какая-то установка, которую я пропустил, чтобы рассказать Джексону/Джерси, чтобы пойти в оба конца для JSON?

+0

Как вы выполняете PUT? Из javascript, командной строки, клиента JAX-RS или что-то еще? –

+0

Извините; Я нашел ответ, что проблема заключалась в том, что Jackson/Jersey автоматически выводит POJO в JSON, но не отменяет его, поэтому мне нужно было удалить аннотацию, связанную с XML, вверху и вручную поместить метод fromString в unmarhsall JSON в объект. –

+0

Джерси определенно может развязать сущности из тела. Я подозреваю, что вы не поставляли правильный заголовок Content-Type (application/json) при выполнении запроса, поэтому мне было интересно, как вы его вызывали (когда я «завиваюсь» из командной строки, я часто забываю «- H 'Content-Type: application/json'). –

ответ

0

я переключение между QueryParam и FormParam, чтобы попытаться получить один из них работать. Если я использую FormParam, мне также необходимо изменить потребление на APPLICATION_FORM_URLENCODED.

Фактическая проблема заключалась в том, что по умолчанию unmarshalling с Jackson использовал XML, потому что он был помечен как XML-ресурс - вытащите это!Наконец, мне удалось разобраться, как отключить JSON, используя статический метод fromString. Затем обрабатывать список; Я не могу использовать класс-оболочку, потому что это должен быть очень перекрестный язык, и публикация обертки со списком усложнила бы реализацию из Python, C# и т. Д. Способ заставить его принять список с оберткой - это опубликовать имя из парама (в данном случае виджетов) несколько раз. Затем каждый переданный JSON будет вызываться против метода fromString.

0

Попробуйте удалить @QueryParam(value = "widgets"), потому что вы должны передать его как тело субъекта - не параметр запроса.

@PUT 
@Path("validateKeys") 
@Produces({MediaType.APPLICATION_JSON}) 
@Consumes(MediaType.APPLICATION_JSON) 
public boolean validateKeys(@QueryParam(value = "page")int page, List<Widget> widgets) 

Также вы можете сделать класс-оболочка:

@XmlRootElement 
public class Widgets { 

    private List<Widget> widgets; 

    // other fields, setters and getters 
} 

И потом:

@PUT 
@Path("validateKeys") 
@Produces({MediaType.APPLICATION_JSON}) 
@Consumes(MediaType.APPLICATION_JSON) 
public boolean validateKeys(@QueryParam(value = "page")int page, Widgets widgets) 

Я хотел бы предложить, чтобы прочитать некоторые дискуссии по поводу дизайна REST, потому что вы используете глаголы в ваших путях :

+0

Спасибо, я отправил ответ выше и спасибо за грамматику REST; Сначала я автогенерировал заглушки кода, которые позже буду очищать при входе в развертывание. –

 Смежные вопросы

  • Нет связанных вопросов^_^