2012-03-07 8 views
5

Attualmente sto lavorando su un'API RESTful. Ho una classe Employee e una classe EmployeeResource. Ho anche un DataAdapter personalizzato, che modifica le mie proprietà Date in data e ora lunghi. Tuttavia, le mie risposte JSON mostrano i timestamp come stringhe (racchiuse tra virgolette doppie) anziché numeri (senza virgolette). Ecco una versione abbreviata del mio codice e la risposta JSON catturato ...JAXB o JAX-RS stanno inserendo numeri nelle mie risposte JSON con le virgolette, trasformandole in stringhe. Perché questo è il comportamento predefinito e come risolverlo?

personalizzato DateAdapter

public class DateAdapter extends XmlAdapter<Long, Date> { 
    @Override 
    public Date unmarshal(Long v) throws Exception { 
     return new Date(Long.valueOf(v)); 
    } 
    @Override 
    public Long marshal(Date v) throws Exception { 
     return v.getTime(); 
    } 
} 

Entity Class

@Entity 
@javax.xml.bind.annotation.XmlRootElement 
@XmlType(propOrder={"createdOn","empId"}) 
public class Employee implements Serializable { 
    private Date createdOn; 
    private Integer empId; 

    @Column(nullable=false) 
    @Temporal(TemporalType.TIMESTAMP) 
    @XmlJavaTypeAdapter(DateAdapter.class) 
    public Date getCreatedOn() { 
     return createdOn; 
    } 
    public void setCreatedOn(Date createdOn) { 
     this.createdOn = createdOn; 
    } 

    @Id 
    @XmlID 
    public Integer getEmpId() { 
     return empId; 
    } 
    public void setEmpId(Integer empId) { 
     this.empId = empId; 
    } 
} 

EmployeeResource

@Path("/Employees") 
@javax.xml.bind.annotation.XmlRootElement 
@XmlType(propOrder={"hateoas","employees"}) 
public class EmployeeResource { 
    List<Employee> employees; 

    public List<Employee> getEmployees() { 
     return employees; 
    } 
    public void setEmployees(List<Employee> employees) { 
     this.employees = employees; 
    } 
    @GET 
    @Path("/{id}") 
    @Produces("application/json") 
    public Response getEmployee(@Context UriInfo ui, @PathParam("id") Integer id) { 
     Session session = HibernateUtil.getSession(); 
     session.beginTransaction(); 
     Criteria criteria=session.createCriteria(Employee.class); 
     criteria.add(Restrictions.eq("empId", new Integer(10150))); 
     this.employees = criteria.list(); 
     return Response.ok(this).build(); 
    } 
} 

risposta JSON corrente

{ 
    "employees":{ 
    "createdOn":"1330915130163", 
    "empId":"10150" 
    } 
} 

risposta JSON atteso

{ 
    "employees":{ 
    "createdOn":1330915130163, 
    "empId":10150 
    } 
} 

Sto supponendo che ci sia un modo per prevenire o JAXB JAX-RS da avvolgere tutti i numeri tra virgolette. Qualcuno potrebbe guidarmi da dove potrei configurarlo?

Grazie in anticipo!

EDIT # 1 2012/03/07 Ok, quindi dopo un po 'di ricerca, penso che il mio problema è con il JSONConfiguration.Notation predefinito in uso, MAPPED. Sembra la JSONConfiguration NATURAL. La notazione mi farebbe ottenere quello che voglio. Tuttavia, non ho trovato un chiaro esempio di come applicare tale applicazione. Presumo che specificherò questo nella mia classe ApplicationConfig che estende javax.ws.rs.core.Application.

EDIT # 2 2012/03/10 Ok, quindi dopo un po 'di ricerche ho deciso di usare la libreria di parser JSON, Jackson. Sembra essere la soluzione JSON più completa là fuori usando solo la configurazione predefinita. Per impostazione predefinita, le date vengono convertite in timestamp corrispondenti e serializzate come numeri (senza virgolette). L'unico inconveniente che ho riscontrato è che Jackson attualmente non supporta le annotazioni JAXB, "@XmlID" e "@XmlIDREF". Dal momento che ho riferimenti auto diretti nel mio modello di dati (non mostrato sopra), ho creato un'altra domanda da discutere. Se qualcuno è interessato click here to follow that thread...

risposta

2

Nota: Sono in vantaggio EclipseLink JAXB (MOXy) e un membro del gruppo di esperti JAXB 2 (JSR-222).

L'implementazione JAX-RS in uso potrebbe utilizzare un'implementazione JAXB (JSR-222) con qualcosa come Jettison per produrre JSON. Jettison fornisce un'API StAX di interagire con JSON, dal momento che le API StAX non hanno alcun tipo di digitazione del testo WRT, tutti i valori semplici sono trattati come stringhe:

Per ottenere risultati il comportamento che stai cercando può utilizzare una diversa soluzione di rilegatura. Stiamo aggiungendo questo supporto nel componente MOXy per EclipseLink 2.4:

Per configurare moxy come provider JSON vincolante in un ambiente JAX-RS, si potrebbe creare una MessageBodyReader/MessageBodyWriter che assomiglia:

import java.io.*; 
import java.lang.annotation.Annotation; 
import java.lang.reflect.Type; 
import java.util.Collection; 
import javax.xml.transform.stream.StreamSource; 

import javax.ws.rs.*; 
import javax.ws.rs.core.*; 
import javax.ws.rs.ext.*; 
import javax.xml.bind.*; 

@Provider 
@Produces(MediaType.APPLICATION_JSON) 
@Consumes(MediaType.APPLICATION_JSON) 
public class MOXyJSONProvider implements 
    MessageBodyReader<Object>, MessageBodyWriter<Object>{ 

    @Context 
    protected Providers providers; 

    public boolean isReadable(Class<?> type, Type genericType, 
     Annotation[] annotations, MediaType mediaType) { 
     return true; 
    } 

    public Object readFrom(Class<Object> type, Type genericType, 
     Annotation[] annotations, MediaType mediaType, 
     MultivaluedMap<String, String> httpHeaders, InputStream entityStream) 
     throws IOException, WebApplicationException { 
     try { 
      Unmarshaller u = getJAXBContext(type, mediaType).createUnmarshaller(); 
      u.setProperty("eclipselink.media-type", mediaType.toString()); 
      u.setProperty("eclipselink.json.include-root", false);//tiny fix 
      return u.unmarshal(new StreamSource(entityStream), (Class) genericType); 
     } catch(JAXBException jaxbException) { 
      throw new WebApplicationException(jaxbException); 
     } 
    } 

    public boolean isWriteable(Class<?> type, Type genericType, 
     Annotation[] annotations, MediaType mediaType) { 
     return true; 
    } 

    public void writeTo(Object object, Class<?> type, Type genericType, 
     Annotation[] annotations, MediaType mediaType, 
     MultivaluedMap<String, Object> httpHeaders, 
     OutputStream entityStream) throws IOException, 
     WebApplicationException { 
     try { 
      Marshaller m = getJAXBContext(Customer.class, mediaType).createMarshaller(); 
      m.setProperty("eclipselink.media-type", mediaType.toString()); 
      m.setProperty("eclipselink.json.include-root", false); 
      m.marshal(object, entityStream); 
     } catch(JAXBException jaxbException) { 
      throw new WebApplicationException(jaxbException); 
     } 
    } 

    public long getSize(Object t, Class<?> type, Type genericType, 
     Annotation[] annotations, MediaType mediaType) { 
     return -1; 
    } 

    private JAXBContext getJAXBContext(Class<?> type, MediaType mediaType) 
     throws JAXBException { 
     ContextResolver<JAXBContext> resolver 
      = providers.getContextResolver(JAXBContext.class, mediaType); 
     JAXBContext jaxbContext; 
     if(null == resolver || null == (jaxbContext = resolver.getContext(type))) { 
      return JAXBContext.newInstance(type); 
     } else { 
      return jaxbContext; 
     } 
    } 

} 

Per ulteriori informazioni

+0

Ciao Blaise, grazie per tutte le informazioni. Ho controllato i collegamenti che hai fornito e, in seguito, li ho utilizzati come base per una pagina che descriveva i diversi valori di JSONConfiguration.Notation. L'aggiornamento di questa notazione predefinita sembra essere quello di cui ho bisogno. Ho aggiornato la mia domanda originale per riflettere questo. – hypno7oad

+1

Ciao Blaise, ho scelto questa come risposta, dato che sono sicuro che funzionerebbe. Tuttavia, non funziona davvero per noi dal momento che è troppo prolisso per il nostro utilizzo. Abbiamo solo bisogno di un modo semplice per abilitare la notazione NATURAL in Jersey piuttosto che la notazione MAPPING predefinita. Detto ciò creerò una nuova domanda, poiché l'esempio di @Provider che ho trovato su Jersey (facendo clic sui collegamenti) non sembra influire sulla mia app. Se potessi commentare anche lì sarei molto riconoscente. Grazie – hypno7oad

Problemi correlati