2013-09-13 1 views
1

Мне нравится строить службу отдыха с помощью ввода и вывода xml и json. Выход xml должен быть корректным и определен в схеме xsd с использованием пространства имен. С помощью xml служба работает хорошо. Для json я не нашел решения для обеспечения согласованного ввода и вывода. Чтобы проиллюстрировать мою проблему, я сделал небольшой пример. Я создал два класса с аннотациями jaxb «Родительский и детский». Родитель имеет атрибут @XmlAttribute и список дочерних объектов. Служба rest может генерировать два примера родительских объектов. Один пример включает одного ребенка, а другой пример - с двумя детьми. Потому что между обозначениями есть список с одним или несколькими членами. Кроме того, служба имеет метод @POST, который получает родительский объект и возвращает его напрямую. Мое предположение заключается в том, чтобы сгенерировать json-текст в методе post и получить те же обозначения, что и раньше. Но это не работает в большинстве случаев.JSON вход/выход службы обслуживания трикотажа не поддерживается в javascript

Моя служба остальное:

@Path("parent") 
public class ParentResource { 

    @GET 
    @Produces ({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) 
    public Parent generateExample(){ 
     Parent father = new Parent(); 
     father.setName("peter"); 

     Child john = new Child(); 
     john.setName("john"); 

     father.getChildren().add(john); 

     return father; 
    } 

    @GET 
    @Path("list") 
    @Produces ({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) 
    public Parent generateExample2(){ 
    Parent father = new Parent(); 
    father.setName("peter"); 

    Child john = new Child(); 
    john.setName("john"); 
    Child sue = new Child(); 
    sue.setName("sue"); 

    father.getChildren().add(john); 
    father.getChildren().add(sue); 

    return father; 
    } 


    @POST 
    @Produces ({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) 
    @Consumes ({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) 
    public Parent echoEntity(Parent input){ 
     return input; 
    } 
} 

Родитель

@XmlAccessorType (XmlAccessType.NONE) 
@XmlRootElement (name="parent") 
public class Parent implements Serializable{ 

    @XmlAttribute 
    private String name; 

    @XmlElement 
    private List<Child> children = null; 

    public String getName() { 
    return name; 
    } 

    public void setName(String name) { 
    this.name = name; 
    } 

    public List<Child> getChildren() { 
    if(children == null){ 
     children = new LinkedList<Child>(); 
    } 
    return children; 
    } 

    public void setChildren(List<Child> children) { 
    this.children = children; 
    } 

}

Детский

@XmlAccessorType (XmlAccessType.NONE) 
@XmlRootElement (name="child") 
public class Child implements Serializable { 

    @XmlElement 
    private String name; 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 
} 

package-info.java в пакете Родитель + Ребенок, чтобы определить пространство имен ,

@javax.xml.bind.annotation.XmlSchema(namespace="http://myexample.com", 
    elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED, 
    attributeFormDefault = javax.xml.bind.annotation.XmlNsForm.UNQUALIFIED) 

Пользовательский контекст распознаватель

@Provider 
@Produces (MediaType.APPLICATION_JSON) 
@Consumes (MediaType.APPLICATION_JSON) 
public class CustomResolver implements ContextResolver<JAXBContext>{ 
    private final JAXBContext context; 
    private final Set<Class<?>> types; 
    private final Class<?>[] cTypes = { 
     Parent.class, Child.class 
    }; 

    public CustomResolver() throws Exception { 
     this.types = new HashSet<Class<?>>(Arrays.asList(cTypes)); 


     Map<String, String> nsMap = new HashMap<String, String>(); 
     nsMap.put("http://myexample.com", "ex"); 

     JSONConfiguration config = JSONConfiguration.natural().rootUnwrapping(false).build(); 
//  JSONConfiguration config = JSONConfiguration.mapped().xml2JsonNs(nsMap).attributeAsElement("name").rootUnwrapping(false).build(); 
//  JSONConfiguration config = JSONConfiguration.mapped().attributeAsElement("name").rootUnwrapping(false).build(); 
//  JSONConfiguration config = JSONConfiguration.mappedJettison().build(); 
//  JSONConfiguration config = JSONConfiguration.badgerFish().build(); 

     context = new JSONJAXBContext(config, cTypes); 
    } 

    public JAXBContext getContext(Class<?> objectType) { 
     return (types.contains(objectType)) ? context : null; 
    } 
} 

Rest приложений, включая пользовательский контекст распознаватель

public class RestApplication extends Application { 
    private Set<Object> singletons = new HashSet<Object>(); 
    private Set<Class<?>> classes = new HashSet<Class<?>>(); 

    public RestApplication(){ 
     singletons.add(new ParentResource()); 

     classes.add(CustomResolver.class); 
    } 

    @Override 
    public Set<Class<?>> getClasses(){ 
     return classes; 
    } 

    @Override 
    public Set<Object> getSingletons(){ 
     return singletons; 
    } 
} 

результатов испытаний, не имеющие пользовательского контекста распознаватель (комментарий в приложении):

generated 1 : 
{"@name":"peter","children":{"name":"john"}} 
output of post method : 
{"@name":"peter"} 

generated 2 : 
{"@name":"peter","children":[{"name":"john"},{"name":"sue"}]} 
output of post method : 
{"@name":"peter"} 

Результаты испытаний с естественной нотации (обозначение я хотел бы использовать)

generated 1 : 
{"parent":{"name":"peter","children":[{"name":"john"}]}} 
output of post method : 
Exception: The request sent by the client was syntactically incorrect() 

generated 2 : 
{"parent":{"name":"peter","children":[{"name":"john"},{"name":"sue"}]}} 
output of post method : 
Exception: The request sent by the client was syntactically incorrect() 

результат теста с отображенной обозначений и без карты пространства имен результата

generated 1 : 
{"parent":{"name":"peter","children":{"name":"john"}}} 
output of post method : 
The request sent by the client was syntactically incorrect() 

generated 2 : 
{"parent":{"name":"peter","children":[{"name":"john"},{"name":"sue"}]}} 
output of post method : 
The request sent by the client was syntactically incorrect() 

Тест с отображенной нотации

generated 1 : 
{"ex.parent":{"name":"peter","ex.children":{"ex.name":"john"}}} 
output of post method : 
{"ex.parent":{"name":"peter","ex.children":{"ex.name":"john"}}} 

generated 2 : 
{"ex.parent":{"name":"peter","ex.children":[{"ex.name":"john"},{"ex.name":"sue"}]}} 
output of post method : 
{"ex.parent":{"name":"peter","ex.children":[{"ex.name":"john"},{"ex.name":"sue"}]}} 

ничего себе оно работает. Но это обозначение, которое я не люблю использовать в javascript. Префиксы пространства имен объединены в имена атрибутов. Это не очень полезно для жесткого кодирования префиксов в клиенте javascript при доступе к вложенным элементам. Имена префиксов могут измениться! С обозначениями сбрасывания он выглядит хуже, чем предыдущие примеры.

Длинная история, но простой вопрос. Есть ли у кого-нибудь решение получить естественную нотацию json и иметь возможность отправлять одну и ту же нотацию в службу поддержки джерси?

ответ

0

Мне удалось обновить его до новой версии трикотажа. Теперь я использую 1.13 до того, как он был довольно старым 1.1.5.1. Я также должен сделать то же самое. В Редакторе контекстного контекста я удалил аннотацию @Consumes (MediaType.APPLICATION_JSON) и добавить новый класс и добавить его к классам в классе приложения

@Provider 
@Consumes (MediaType.APPLICATION_JSON) 
public class NaturalJsonReader implements MessageBodyReader{ 

    private static final JSONConfiguration jConfig = JSONConfiguration.natural().rootUnwrapping(false).build(); 

    @Override 
    public boolean isReadable(Class arg0, Type type, Annotation[] arg2, MediaType mt) { 
     return true; 
    } 

    @Override 
    public Object readFrom(Class arg0, Type arg1, Annotation[] arg2, MediaType arg3, MultivaluedMap arg4, InputStream arg5) throws IOException, WebApplicationException { 

     try { 
      JSONUnmarshaller m = new JSONJAXBContext(jConfig, arg0).createJSONUnmarshaller(); 
      Object o = m.unmarshalJAXBElementFromJSON(arg5, arg0).getValue(); 
      return o; 
     } catch (JAXBException e) { 
     } 

     return null; 
    } 
} 

После этого естественное обозначение может использоваться для ввода и вывода работы остальных служб.

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