I have some incoming JSON that I need to map to a JAXB object. Do I need to convert the JSON to XML and then populate the JAXB object, or can I map the JSON directly to the object? In either case, can someone tell me what is the best library for doing this?
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
Do I need to convert the JSON to XML and then populate the JAXB
object, or can I map the JSON directly to the object?
You do not need to convert the JSON to XML before you hand the input to a JAXB (JSR-222) implementation. If you are using the Jersey implementation (and probably others), you can set up your JAX-RS method like the following and JAXB will be used for both XML and JSON processing.
#GET
#Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
#Path("{id}")
public Customer read(#PathParam("id") long id) {
return entityManager.find(Customer.class, id);
}
JAX-RS implementations have a MessageBodyReader/MessageBodyWriter mechanism that allow you to override the default conversion. I am not aware of Gson having any support for JAXB annotations. Jackson is a object-to-JSON library that offers support for a subset of JAXB annotations (maybe regrettably). EclipseLink MOXy is a JAXB implementation, that has been extended to support JSON-binding. For an example of using it in a JAX-RS environment see:
http://blog.bdoughan.com/2012/05/moxy-as-your-jax-rs-json-provider.html
gson is a flexible library that can convert JSON string to equivalent Java objects including pre-existing Java objects.
If you are using Jackson, You could look at the JacksonJAXBAnnotations here http://wiki.fasterxml.com/JacksonJAXBAnnotations
As a lightweight approach, you can use StAXON - JSON via StAX, https://github.com/beckchr/staxon/. StAXON provides support for JAXB, see https://github.com/beckchr/staxon/wiki/Using-JAXB.
With StAXON, binding a JAXB-annotated model to JSON is as simple as
JsonXMLMapper<Person> mapper = new JsonXMLMapper<Person>(Person.class);
Person person = mapper.readObject(input);
...
mapper.writeObject(output, person);
StAXON also supports JAX-RS, see https://github.com/beckchr/staxon/wiki/Using-JAX-RS.
Related
I have this simple code:
package com.example
import javax.json.Json;
import javax.json.JsonObject;
...
#Path("/")
public class Resource {
#GET
#Produces(MediaType.APPLICATION_JSON)
public Response defaultEntry() {
JsonObject result = (Json.createObjectBuilder()
.add("hello", "world")
.build());
return Response.status(200).entity(result.toString()).build();
}
}
I am new to Java, could someone please explain why, if I omit the call to result.toString() and simply pass result to .entity (like so: return Response.status(200).entity(result).build()), I get JSON on the client that includes type information etc, but not what I expected:
{"hello":{"chars":"world","string":"world","valueType":"STRING"}}
what is the intention of this? How is passing JsonObject to it different from passing a string?
Also, I did not find Response.entity method in the documentation (https://jersey.java.net/apidocs/2.11/jersey/javax/ws/rs/core/Response.html). I copied this code from a tutorial, that did not explain properly what is going on...
I wish I had a better answer for you, this more of a hint until a better answer arrives. There are a few moving parts here. JsonObject is an interface. Its implementation is not described. Furthermore there is a Json serializer that is turning your returned objects into Json text. It is both these things together that is leading to this Json schema output. When you did the .toString() variation, the serializer just returned the String as is. But when you return the JsonObject now you have these two dynamics at play, the implementation of the JsonObject and the implementation of the serializer. Since you are using Jersey 2.0 you could be using Jackson, Moxy, or Jettison serializers. These all might have different output when serializing the JsonObject, but we would have to test to be sure. Furthermore, the JsonObject implementation might be configured in a way that when serialized by your chosen serializer leads to its output being a Json schema, versus just regular Json. This can be done using annotations that are specific to the chosen Json serializer.
In my career I have used multiple Json serializers. Jackson is probably the most popular one out there. But I have also used Gson extensively. In one project we configured Gson in some way where its serialized Json output came out as a Json schema when serializing POJO's. So its not far fetched to have a Json serializer output Json schema under certain conditions.
When serializing POJO's (aka Java Beans), you expect a regular Json output when using default settings of your serializer on a Java Bean. But when sending back objects that could have complex interworkings with specific Json serializers you may get varying Json output.
In this situation you would have to run tests to dive deeper into what is going on. For example, I would first test out the serializer against a POJO that matches the JsonObject you created. Then I would also test out other Json serializers on the same JsonObject. See if you can pick up on a pattern.
The datatype module jackson-datatype-jsr353 provides support for javax.json types. The page includes instructions how to add the dependency and register the module with Jackson's ObjectMapper.
Starting with Jackson 2.11.0, the module moved under the umbrella of jackson-datatypes-misc.
We get a org.codehaus.jackson.map.exc.UnrecognizedPropertyException with using Jerseys and Jackson as JSON-Mapper. We have an object with not native type as property (for example: not a String or int). When i use the annotation #JsonIgnore it's ok. But I must have the property.
Does anybody, which annotation should I use? In JAXB it's #XMLType?
We use Jersey 1.9.1 and Jackson 1.9.13.
I solved this. See my comment on the question.
I've got a very simple problem here, but after using Google for over an hour now, I still cannot find a good solution and it starts to cost too much money..
In my app I use REST as an API, basically only with JSON as payload type, and Enunciate for documentation of the API. As you might know, enunciate will generate an xsd schema from the classes. I am therefore in the situation, that I need to configure all the DTO's for Jackson/JSON handling with the suitable annotations, and also with JAXB annotation to ensure the generated schema is correct and can be parsed with XJC into the correct classes!
Although that is not very difficult to achieve and works flawless in most of the cases, I have a simple but somehow special case, in which it completely fails.
Assuming the following classes:
#JsonRootName(value = "location")
public class Location {
private String label;
#JsonUnwrapped
private Address address;
// constructors, getters, setters ommited..
}
//// new file
public class Address{
private String city;
private String street;
private String postCode;
}
This works 100% with Jackson/JSON. The embedded Address object will be unwrapped so that the JSON looks like this:
{
"label":"blah",
"street":"Exchange Road",
"city":"Stacktown"
"postCode":"1337"
}
This works forth and back with Jackson.
JAXB on the other hand is able to parse (most of) the Jackson annotations, so that generally you wont have problems with using simple objects in both worlds. #JsonUnwrapped though sadly is NOT supported by JAXB, and strangely that (from my POV) quite simple usecase seems to be not reflectable with any JAXB annotation at all.
What happens is, that the generated schema contains the embedded Address object, without any attributes/elements. Therefore the class generated by XJC will contain that Address object reference. And this ultimately leads to erroneous JSON from a app that will use the schema to generate objects...
Any ideas?
The JAXB (JSR-222) specification does not define an equivalent to Jackson's #JsonUnwrapped. For a long time we have offered that functionality in the EclipseLink MOXy implementation of JAXB via our #XmlPath extension.
#XmlPath(".")
private Address address;
For More Information
I have written more about MOXy's #XmlPath extension on my blog:
http://blog.bdoughan.com/2010/07/xpath-based-mapping.html
I've been looking at the couchbase-java-client project and wondering whether it's possible to use it inside of a dropwizard project.
It seems like it'd be a natural fit, because couchbase is basically a JSON database, but the java client doesn't seem to be compatible with Jackson. As far as I can tell, the couchbase client library includes its own internal implementation of a JSON library that's incompatible with all the other java JSON libs out there, which is really weird.
I found a JacksonTransformers class that looked promising at first. But upon closer inspection, the library is using a shaded version of Jackson (with a rewritten package of com.couchbase.client.deps.com.fasterxml.jackson.core).
Anyhow, since dropwizard uses Jackson and Jersey for marshalling JSON documents through the REST API, what's the least-friction way of using the couchbase-java-client library? Is it even possible in this case?
It is definitely possible to use Couchbase with Dropwizard. The client SDK provides JSON manipulation objects for the developer's convenience but it also allows for delegating JSON processing to a library like Jackson or GSON.
Take a look at the RawJsonDocument class here.
Basically, you can use a Stringified JSON (coming out of any framework) to create one of those objects and the client SDK will understand it as a JSON document for any operation i.e.:
String content = "{\"hello\": \"couchbase\", \"active\": true}";
bucket.upsert(RawJsonDocument.create("rawJsonDoc", content));
It should be possible to make this work.
Client requests to dw server for Resource Person.
DW server requests to couchebase, gets a Pojo back representing Person or JSON representing person.
If it's JSON, create a POJO with Jackson annotations in DW and return that to client
If it's a special couchebase pojo, map that to a Jackson pojo and return to to client
A solution based on #CamiloCrespo answer:
public static Document<String> toDocument(String id, Object value,
ObjectMapper mapper) throws JsonProcessingException {
return RawJsonDocument.create(id, mapper.writeValueAsString(value));
}
Keep in mind, that you can't use a simply maper, like ObjectMapper mapper = new ObjectMapper(), with Dropwizard.
You can get it from Environment#getObjectMapper() in the Application#run() method, or use Jackson.newObjectMapper() for tests.
An example of using:
ObjectMapper mapper = Jackson.newObjectMapper();
User user = User.createByLoginAndName("login", "name");
bucket.insert(toDocument("123", user, mapper));
Does anyone know if there is the ability to generate objects for JSON data? I know there are generic JSON object libraries, but I am looking for more specific - similar to how jaxb can convert SOAP definitions or XSDs into an object model. I know there would need to be some sort of JSON definition file (which I do not know if that concept even exists within JSON), but I feel like that would be a lot more beneficial. Think:
Generic case:
genericJsonObect.get("name");
Specific case:
specificJsonObject.getName();
Jackson and XStream have the ability to map json to POJOs.
Do you want the .java source file to be generated for you? Or to map exiting java beans to JSON objects?
If the former, there is no such a library ( that I'm aware of ) if the later, Google GSON is exactly what you need.
From the samples:
class BagOfPrimitives {
public int value1 = 1;
private String value2 = "abc";
private transient int value3 = 3;
BagOfPrimitives() {
// no-args constructor
}
}
(Serialization)
BagOfPrimitives obj = new BagOfPrimitives();
Gson gson = new Gson();
String json = gson.toJson(obj);
System.out.println( json );
Prints
{"value1":1,"value2":"abc"}
( Deserialization )
BagOfPrimitives obj2 = gson.fromJson(json, BagOfPrimitives.class);
System.out.println( obj2.value1 ) ; // value1 is 1
I think the Jackson data mapper can do what you need. It can serialize/deserialize a real Java object into a Json tree.
But others API should also work :
Sojo
FlexJSON
Gson
I am not familiar of such code generation project, although I am sure many Java JSON library projects would be interested in having such thing. Main issue is that there is good Schema language for JSON that would allow code generation; JSON Schema only works for validation.
However: one possibility you could consider is to just use JAXB to generate beans, and then use Jackson to use those beans. It has support for JAXB annotations so you would be able to work with JSON and beans generated.
I have found this site very useful.
http://jsongen.byingtondesign.com/ and have used it in our projects.