Jackson Custom Mapper to convert Byte Array to String - java

I'm incredibly new to Jackson and I have a problem with understanding how I could accomplish something.
I've got some data that is of type byte[] (the data is within classes generated from JAXB). Before the data is sent to the browser, Jackson then (I believe) turns it into JSON so that the webpage can consume it. At least that is my crude understanding, so far.
The JSON data shows my byte [] as strings, which don't match the display that we want. For instance, the actual data might be CAFEDEAD but the JSON string looks like 3q2+78r+. I'd like the JSON to contain the string CAFEDEAD
My question is, can I write something custom for Jackson that before it creates the final JSON, turn the byte[] data into a readable hex string? Or if not, what other options do I have?
I have access to the javascript so if there is a way to turn the JSON string back, i'm up for that as well.

Jackson will convert byte[] into Base64-encoded binary data. This is the safe way to pass binary content. Otherwise there is no way to know which character encoding might be used by contained data, so trying to build a String out of it would be risky and error-prone.
So the simplest way would be to have receiver base64 decode contents back into binary data.
You could alternatively add custom serializer to turn into other representations (hex, base85), but it really depends on what the goal is.

Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
Below is how you could support this use case with MOXy as your JSON-binding provider.
Java Model
By default a JAXB implementation will convert a byte[] to base64Binary. You can use the HexBinaryAdapter to have it represented as hexBinary.
package forum15643723;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.*;
#XmlAccessorType(XmlAccessType.FIELD)
public class Root {
private byte[] foo;
#XmlJavaTypeAdapter(HexBinaryAdapter.class)
private byte[] bar;
}
Demo
In the demo code below we will read the JSON into objects and then write it back to JSON.
package forum15643723;
import java.util.*;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;
import org.eclipse.persistence.jaxb.JAXBContextProperties;
public class Demo {
public static void main(String[] args) throws Exception {
Map<String, Object> properties = new HashMap<String, Object>();
properties.put(JAXBContextProperties.MEDIA_TYPE, "application/json");
properties.put(JAXBContextProperties.JSON_INCLUDE_ROOT, false);
JAXBContext jc = JAXBContext.newInstance(new Class[] {Root.class}, properties);
Unmarshaller unmarshaller = jc.createUnmarshaller();
StreamSource json = new StreamSource("src/forum15643723/input.json");
Root root = (Root) unmarshaller.unmarshal(json, Root.class).getValue();
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
jaxb.properties
To specify MOXy as your JAXB provider you need to include a file called jaxb.properties in the same package as your domain model (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html).
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
input.json/Output
The foo and bar properties represent the same data. foo is represented as base64Binary and bar is represented as hexBinary.
{
"foo" : "3q2+78r+",
"bar" : "DEADBEEFCAFE"
}
For More Information
http://blog.bdoughan.com/2011/08/json-binding-with-eclipselink-moxy.html

You can use #JsonSerialize and #JsonDeSerialize annotations over any property. javadoc is at
http://jackson.codehaus.org/1.2.1/javadoc/org/codehaus/jackson/map/annotate/JsonSerialize.html
I would personally use the serialization/deserialization technique rather than conversion at client side as you probably end up doing it at multiple places.

Without any code, I had to guess what you are doing according to your question. This tutorial JSON parse to / from using Jackson shows you how to convert ObjectMapper to a Stringfiyed representation of JSON for example
"{"age":29,"messages":["msg 1","msg 2","msg 3"],"name":"mkyong"}"
Then when Javascript client receives this String, you are going to have to parse this using either built in JSON parse function or jQuery provided one. Like
...
var myJson = JSONString.parse() | jQuery.parseJSON(JSONString);
..
myJson.age; //29
myJson.name; //"mkyong"
Reason for attempting to parse it using parse() first is to avoid using jQuery while there is already a built in function for this provided by browser. However, if this function is not detected, it will parse it through jQuery.
I hope this helps
For your interest
Your data example appears to be some kind of binary data and you are attempting to send it over the networks. This might cause routers to filter these data. If you are interested, you can have a look at encoding this data into Base64 before streaming it to the client. It is very easy to do because there are many libraries out there already.
Some resources regarding to this topic.
So it is going to be like
SERVER
1) Jackson creates JSON String
2) Server encodes into Base64
3) Send
CLIENT
1) Receive
2) Decode base64
3) parse JSON String

Related

Modeling JSON in Java

The few times I've worked with Java/Rest/JSon, JSON elements have always been built in camelCase format.
For example:
"someField": {
"someSonField1": "20191106",
"someSonField2": "20201119",
...
}
However, in a functional document they have passed me to build a Rest JSon client, they use this notation:
"some_field": {
"some_son_field_1": "20191106",
"some_son_field_2": "20201119",
...
}
Is it expressed somewhere that Java has to use the notation 1?.
It seems to me that if it is done this way, everything goes much more smoothly when modeling the objects:
#XmlRootElement(name = "someField")
#XmlType(propOrder = {"someSonField1", "someSonField2"})
public class someField {
private String someSonField1;
private String someSonField2;
//...
}
Thanks!
Q: Is it expressed somewhere that Java has to use the notation?
A: No: it's 100% "convention", not mandatory.
As it happens, the standard convention for both JSON (a creature of Javascript) and Java is camelcase. For example: Java Naming Conventions.
some_son_field_1 is an example of snake case. It's associated with classic "C" programs. It's also common (but NOT universal) with XML. It, too, is a "convention" - not a requirement.
I'm curious why you're choosing XML bindings for JSON data. Have you considered using Jackson?
Finally, this article might be of interest to you:
5 Basic REST API Design Guidelines
I see you're using javax.xml.bind package? Have you tried #XmlElement?
#XmlRootElement(name = "someField")
#XmlType(propOrder = {"some_son_field_1", "some_son_field_2"})
public class someField {
#XmlElement(name="some_son_field_1")
private String someSonField1;
#XmlElement(name="some_son_field_2")
private String someSonField2;
//...
}
Not sure, probably you should try putting them on getters, as your fields are private.
Or you could use unify-jdocs, a library which I created to read and write JSON documents without using any POJO objects. Rather than defining POJO objects, which we know can be difficult to manage in case of complex documents and changes to the JSON document, just don't use them at all. Directly read and write paths in the JSON document. For example, in your snippet, you could read and write the fields as:
Document d = new JDocument(s); // where s is a JSON string
String s1 = d.getString("$.some_field.some_son_field_1");
String s2 = d.getString("$.some_field.some_son_field_2");
You could use a similar way to write to these paths as so:
d.setString("$.some_field.some_son_field_1", "val1");
d.setString("$.some_field.some_son_field_2", "val2");
This library offers a whole lot of other features which can be used to manipulate JSON documents. Features like model documents which lock the structure of documents to a template, field level validations, comparisons, merging documents etc.
Obviously, you would consider it only if you wanted to work without POJO objects. Alternatively, you could use it to read and write a POJO object using your own method.
Check it out on https://github.com/americanexpress/unify-jdocs.

Why My program Return String Value in XML format?

I am using a Web service and it returns a String value. But in my output, that value is in XML format:
String point = request.getParameter("point");
try {
String latLonListCityNames = proxy.latLonListCityNames(new BigInteger(point));
request.setAttribute("point", latLonListCityNames);
System.out.println(latLonListCityNames);
} catch (RemoteException e) {
e.printStackTrace();
}
I expect the output to be for example "Oklahoma", but the actual output is:
<?xml version='1.0' ?>
<dwml version='1.0' xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd">
<latLonList>
<cityNameList>
Oklahoma
</cityNameList>
</dwml>
The responses of web-services are commonly (not always) in XML. If you need to extract the data from xml string response to your desired format, say, Java Objects (POJO), you need a converter i.e. marshaling and Un-marshaling of data.
Simple solution
Use JAXB.
What is JAXB? From wiki
Java Architecture for XML Binding (JAXB) is a software framework that allows Java developers to map Java classes to XML representations. JAXB provides two main features: the ability to marshal Java objects into XML and the inverse, i.e. to unmarshal XML back into Java objects.
How does it fit into my use-case?
Create a simple POJO for the type of response you are expecting. And then use JAXB convertor to convert them for you.
Eg. If you are expecting a list of cityName in response, you can create your POJO like below..
CityModel.java
public Class CityModel {
private List<String> cityName;
// if more field required, add here.
}
Sample XML response should be..
<ListOfCities>
<CityName>My City</CityName>
<CityName>Your City</CityName>
<CityName>So Pity</CityName>
</ListOfCities>
Then, pass this xml response string to JAXB binding for Equivalent Class type. i.e. CityModel.
How to do all this? Can You Share some good example?
Read this tutorial to get started.
I have problem with the response type names, they are not well described, how can I map them with different name that I want?
You might need to look at links below, they key part is investigate more about #XmlRootElement, #XmlAttribute, #XmlElement, etc annotations for custom configurations.
Few more important links that can help later on?
Convert Soap XML response to Object
convert xml to java object using jaxb (unmarshal)
Using JAXB for XML With Java
JAXB Unmarshalling Example: Converting XML into Object

After I got XML data, how to parse it and transfer to JSON?

In Jersey RESTful frame work, I know I can get xml data in client as following:
private static final String BaseURI = "http://DOMAN.com";
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
WebResource service = client.resource(BaseURI);
String xmlData = service.path("rest").path("todos").accept(
MediaType.APPLICATION_XML).get(String.class)
My question is how can I parse the xmlData then? I would like to get the needed data from xmlData, and transfer the needed data to JSON, what is the best way to implement this?
As a general rule, NEVER convert straight from XML to JSON (or vice versa) if you do not have to.
Rather, bind data from XML or JSON to POJOs, then do the other conversion. While it may seem non-intuitive this results in cleaner result and less problems, since conversions between POJOs and data formats have much more options, mature, well-designed libs; and POJOs are easier to configure (with annotations) and have more metadata to guide conversion process.
Direct conversions libs (like Jettison, see below) are plagued with various issues; often producing "franken-JSON", JSON that is technically correct but looks alien because of added constructs needed by conversion.
In case of Jersey, then, use JAXB for XML to/from POJOs, and Jackson for doing the same with JSON. These are libraries Jersey uses anyway; and direct usage is quite easy.
If you absolutely insist on direct conversion, you could try Jettison, but be prepared to hit a problem with Lists, arrays and Maps, if you need them (esp. single-element arrays -- arrays are problematic with XML, and auto-conversion often goes wrong).
If your service doesn't provide JSON as an option already (what happens if you change MediaType.APPLICATION_XML to MediaType.APPLICATION_JSON?), then I believe you have a few options, which I list in order of my preference.
Option 1: You have an XML schema for the the data
If you have an XML schema for the returned XML, you could use xjc to generate the JAXB annotated java classes and then leverage jackson to convert the instances to JSON data. I think this will get you going fast by leveraging this libraries over doing the parsing youself. Jackson is a robust library, used by glassfish for their Jersey(JAX-RS) implementation and I don't feel there is any risk in depending on this library.
Option 2: Use the json.org library, but I've had significant problem with this library having to do with its reflection-based methodology, etc. That said, it might work well for you...and you can test relatively easily and see if it does meet your requirements. If so...you're done! =)
Option 3: You don't have the XML schema and/or you want more control
as #Falcon pointed out, you can always use traditional XML parsing technologies to parse the XML into whatever you want. I'm partial to SAX parsing, but DOM could work depending on xml side
Regards,
Steve
Simplest and easiest way would be using org.json package : http://json.org/javadoc/org/json/XML.html
XML.toJSONObject(xmlData).toString()
Just this one line apart from necessary import statement will do it all.
Now that i have mentioned org.json library, lot of people may comment bad about it. Remember, I have said the simplest and easiest way, not the best or the most performant way ;-)
In case you are using maven, add this dependency :
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20090211</version>
</dependency>
Do you have any access to the "lower level interface" that generates the XML? If you do, the only change needed is to have the xml objects annotated with "#XmlRootElement". Then, you can just pass back the XMLobject as JSON without any further code.
Check Jsonix. If you have an XML schema, you can generate XML-JSON mappings and unmarshal/marshal XML in JavaScript. Very similar to JAXB (which Steve Siebert mentioned), but works on client.
// The PO variable provides Jsonix mappings for the purchase order test case
// Its definition will be shown in the next section
var PO = { };
// ... Declaration of Jsonix mappings for the purchase order schema ...
// First we construct a Jsonix context - a factory for unmarshaller (parser)
// and marshaller (serializer)
var context = new Jsonix.Context([ PO ]);
// Then we create an unmarshaller
var unmarshaller = context.createUnmarshaller();
// Unmarshal an object from the XML retrieved from the URL
unmarshaller.unmarshalURL('/org/hisrc/jsonix/samples/po/test/po-0.xml',
// This callback function will be provided with the result
// of the unmarshalling
function(result) {
// We just check that we get the values we expect
assertEquals('Alice Smith', result.value.shipTo.name);
assertEquals('Baby Monitor', result.value.item[1].productName);
});

Display null for objects -JSON- JAXB

I want to marshal null objects as null in the JSON representation.
But, right now, Am not seeing the element in the JSON if the object is null.
Example:
#XmlAccessType(FIELD)
#XmlType(name="foo" propOrder={"foo"}
class foo{
#XmlElement
private Integer foo;
private Integer another_foo;
..
getter()
setter()
}
In my code am setting foo element to null.
But the JSON representation does not show the element in the response.
The response looks like this
"foo" :{
"another_foo":something
}
I tried setting xml element attribute nillable true. (#XmlElement(nillable=true)
Which makes the response look like,
"foo" :{
"another_foo" : something
"foo":{nil :true}
}
I want it to be like,
"foo" :{
"another_foo":something
"foo" : null
}
What am doing wrong here?
First things first: JAXB does NOT do JSON. It is an XML API. So you are probably using a framework (my guess: JAX-RS implementation like maybe Jersey)? It is necessary to know which one you are using to give more help.
Assuming this, question is, how is the package using JAXB annotations to guide JSON serialization. Some basically convert objects to XML (either logical structure, or full xml), and then convert to JSON using a convention. This may cause data loss because of differences in data model between XML and JSON.
Now: simple solution for most JAX-RS implementations is to not use JAXB annotation based approach at all, but a JSON-specific serializer, such as Jackson's JacksonJsonProvider (Jackson can actually use JAXB annotations, too). It will by default include null values for properties, although this is configurable in case you want to suppress nulls.
Here is JavaDoc that shows how to use Jackson provider (specify FEATURE_POJO_MAPPING for configuration) with Jersey, if that might help.
i think the functionality of json is like that only, it will not show you null values in the Json string. Suppose an example, you have an object with two attributes say age and name. Now if the age is 7 and name is null, then if according to you, name should also be included in the JSON object then, u must right the code to explicit handle the deserialization of the same code. then you will have to handle the null value thing as JSON will treat "null" as a string and will assign it to the object which will make your object with name="null", which is wrong.
If you want to achieve the same, then you must extend the class JSON object and write your own implementation.
Note: I'm the EclipseLink JAXB (MOXy) lead and member of the JAXB (JSR-222) expert group.
EclipseLink JAXB (MOXy) offers native support for JSON. Below is an example of how the #XmlElement annotation can be leveraged to map your use case:
Foo
By default a JAXB implementation will not marshal a null property. You can change this behaviour by setting the nillable property on #XmlElement to true.
package forum3938279;
import javax.xml.bind.annotation.*;
#XmlAccessorType(XmlAccessType.FIELD)
class Foo {
#XmlElement(nillable=true)
private Integer foo;
private Integer another_foo;
}
jaxb.properties
To specify MOXy as your JAXB provider you must include a file called jaxb.properties in the same package as your domain model with the following entry:
javax.xml.bind.context.factory = org.eclipse.persistence.jaxb.JAXBContextFactory
Demo
package forum3938279;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Foo.class);
Foo foo = new Foo();
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty("eclipselink.media-type", "application/json");
marshaller.marshal(foo, System.out);
}
}
Output
Below is the output from running the demo code. Both fields had null values. The field without the #XmlElement annotation was not marshalled, and the one with #XmlElement(nillable=true) was marshalled as expected in JSON.
{
"foo" : null
}
For More Information
http://blog.bdoughan.com/2011/08/json-binding-with-eclipselink-moxy.html

Is there a library to convert Java POJOs to and from JSON and XML? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking us to recommend or find a tool, library or favorite off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it.
Closed 8 years ago.
Improve this question
I have an object graph that I would like to convert to and from JSON and XML, for the purposes of creating a REST-style API. It strikes me that someone must have done this already, but a quick search using Google and Stack Overflow reveals nothing.
Does anyone know of a suitable (Apache or equivalent license preferred) library to do this?
GSON from google : http://code.google.com/p/google-gson/,
or
Jackson the library used in spring :https://github.com/FasterXML/jackson
and I would concur with others suggesting jaxb for XML to pojo, well supported lots of tools : its the standard.
For POJO to XML I suggest using JAXB (there are other libraries as well, such as XStream for example, but JAXB is standardized).
For JSON I don't know anything, but if you want to implement a RESTful API, you might be interested in JSR-311 which defines a server-side API for RESTful APIs and Jersey, which is its reference implementation.
Use Xstream http://x-stream.github.io/ for xml and JSON http://www.json.org/java/ for JSON. I dont think there is one library that does both.
Or write a wrapper which delegates to XStream renderers/JSON renderers depending on what you want.
I think you may be looking for something similar to what is here: JSON.org Java section
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
EclipseLink JAXB (MOXy) supports mapping a single object model to both XML and JSON with the same metadata:
http://blog.bdoughan.com/2011/08/binding-to-json-xml-geocode-example.html
License Information
http://wiki.eclipse.org/EclipseLink/FAQ/General#How_is_EclipseLink_Licensed.3F
DOMAIN MODEL
Below is the domain model we will use for this example. For this example I'm just using the standard JAXB (JSR-222) annotations which have are available in the JDK/JRE since Java SE 6.
Customer
package forum658936;
import java.util.List;
import javax.xml.bind.annotation.*;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
String firstName;
#XmlElement(nillable=true)
String lastName;
#XmlElement(name="phone-number")
List<PhoneNumber> phoneNumbers;
}
PhoneNumber
package forum658936;
import javax.xml.bind.annotation.*;
#XmlAccessorType(XmlAccessType.FIELD)
public class PhoneNumber {
#XmlAttribute
int id;
#XmlValue
String number;
}
jaxb.properties
To specify MOXy as your JAXB provider you need to include a file called jaxb.properties in the same package as your domain model with the following entry (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html).
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
XML
input.xml
This is the XML that our demo code will read in and convert to domain objects.
<?xml version="1.0" encoding="UTF-8"?>
<customer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<firstName>Jane</firstName>
<lastName xsi:nil="true"/>
<phone-number id="123">555-1234</phone-number>
</customer>
Things to note about the XML:
The xsi:nil attribute is used to indicate that the lastName is null.
The phone-number element is a complex type with simple content (see: http://blog.bdoughan.com/2011/06/jaxb-and-complex-types-with-simple.html).
JSON
Output
Below is the JSON that was output by running the demo code.
{
"firstName" : "Jane",
"lastName" : null,
"phone-number" : [ {
"id" : 123,
"value" : "555-1234"
} ]
}
Things to note about the JSON:
The null value is used to represent that the lastName is null. There is no presence of the xsi:nil attribute.
The collect of phone numbers is of size 1 and is correctly bound by square brackets. Many libraries incorrectly treat collections of size 1 as JSON objects.
The property of type int was correctly marshalled without quotes.
In the XML representation id was an attribute, but in the JSON representation there is not need for it to be specially represented.
DEMO CODE
In the demo code below we will convert an XML document to objects, and then convert those same instances to JSON.
Demo
MOXy doesn't just interpret JAXB annotations it is a JAXB implementation so the standard JAXB runtime APIs are used. JSON binding is enabled by specifying MOXy specify properties on the Marshaller.
package forum658936;
import java.io.File;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.MarshallerProperties;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Customer.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum658936/input.xml");
Customer customer = (Customer) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/json");
marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
marshaller.marshal(customer, System.out);
}
}
Json-lib is licensed under the Apache 2.0 license.
It can also transform JSON objects to XML, but you'd need to convert your POJOs to JSON through it first.
Personally I would tackle the two separately; and to convert JSON<->XML via JSON<-> Pojo <-> XML.
With that: Java<->POJO with JAXB (http://jaxb.dev.java.net; also bundled with JDK 1.6) with annotations (XStream is ok too); and for JSON, Jackson's ObjectMapper (http://jackson.codehaus.org/Tutorial). Works nicely with Jersey, and I am use it myself (current Jersey version does not bundle full Pojo data binding by default, but will in near future)
I would actually not use any of xml libs to produce "json": XStream and JAXB/Jettison can produce kind of JSON, but it uses ugly conventions that are rather non-intuitive.
EDIT (18-Jul-2011): Jackson actually has an extension called "jackson-xml-databind" that can read/write XML, similar to JAXB. So it can be used for both JSON and XML, to/from POJOs.
Last I saw on the website, XStream will do both. It supports XML and JSON as serialization targets.
There are almost literally hundreds. My favorites are GSON for POJO <-> JSON and castor-xml for POJO <-> XML.
As a bonus both are licensed under Apache License 2.0 style licenses.
Have a look at Genson library http://code.google.com/p/genson/wiki/GettingStarted.
It is easy to use, performant and was designed with extension in mind.
Actually it does json/java conversion but not xml. However xml support may be added in a future version.
I'm using it in web applications and REST web services in jersey, but also in some cases to store objects in their json form into a database.
Ah and it's under Apache 2.0 license.

Categories

Resources