I'm generating a Java class hierarchy from a complicated xml schema. The content stored in xml (returned via a REST endpoint) is verbose, plus consumers want only subsets of the xml content returned as json (that they define).
I know there are brute force ways to accomplish this, but does anyone know of a more elegant approach? Maybe some kind of mapping that the consumer could pass to the service that would allow them to dynamically select the content (via xpath in the mapping) and also produce custom json wrapping that content?
The consumers will have an understanding of the schema and content structure, but nothing about Java or its object hierarchy.
I know, a lot here. Any suggestions?
You can give Apache Commons JXPath a try. If you have the Java class hierarchy then I assume you have the objects in memory before sending them as XML. With that you can user JXPath to traverse the java objects as if they were XML in XPath fashion.
Related
According to James Wards Play Tutorial it's very easy to get a JSON out of your model. Also with XML this should be quite simple.
But most of the time, I have the requirement to build not just an plain XML or JSON Endpoint, but furthermore to deliver special flavours of those. In my case this is GeoJSON or TopoJSON. But also in XML, it could be a simple RSS or ATOM Feed you have to deliver out of your model. Also building a XML fitting to a very nasty XSD schema is still a case sometimes.
What options do you have in play to perform this, or which one of the following would you recommend?:
In case of GeoJSON/TopoJSON: Activate JSON as a template format, and create JSON Templates
In case of ATOM/RSS: Just use an XML Template
Some way to modify the JSON response coming from toJson(tasks)?
Use of a fancy library which does all that out of the box, and everyone knows about it, except me?
If you're doing GeoJSON, just annotate your objects with Jackson annotations according to the GeoJSON spec, it's not hard. If it is hard, then there are a few libraries out there that come with Java objects with the necessary annotations already for you, eg: https://github.com/opendatalab-de/geojson-jackson
An XML template is probably the simplest from Java.
What's your use case? toJson returns a Jackson JSONNode. You can modify it as much as you want. But the better thing to do would be to use Jackson annotations on your objects to get the format right in the first place.
I think you're referring to Jackson, it can do everything you want. It can even do XML if you want it to.
I am using java, I want to read strings from an XML tag. EX: < blank type="Something">
I need to be able to assign "Something" to a variable. Any ideas?
There are a lot of ways to do this:
You can use the XML APIs provided with Java (SAX or STAX or DOM).
There are libraries that build on the XML APIs (JDOM, DOM4J, or XOM) which are easier to use than the raw APIs.
There's Java-XML databinding, described in Pratik's answer. Java-XML databinding is sometimes overkill, depending on your requirements, and when there are errors they can be hard to figure out. Sometimes it's worthwhile, though. I think JiBX is particularly interesting.
If you don't know where to start, start with XOM. XOM was created by a JDOM contributor, it was designed to be easy to use.
What you want to achieve is referred to as Unmarshalling an XML. Unmarshalling means extracting data from an XML document and using it to construct a Java object or graph of objects. There are various APIs available to do the same. You should have a look at the following links:
JAXB:
http://www.oracle.com/technetwork/articles/javase/index-140168.html
Castor: http://castor.codehaus.org/
JiBX: http://jibx.sourceforge.net/
Let's say I have REST like endpoints which return JSON data, e.g. from models in my Java Play application. I've found two ways to create the JSON output:
Using JSON templates similar to HTML templates. It could look like this:
{
"name": "${user.name}",
"id": "${user.id}",
. . .
}
What I like about it is the flexibility. I could build a wrapper around the data (for metadata, status messages etc.) with ease. And I easily can influence which things get delivered (things like password fields, timestamps of last login etc. are of course nothing you want to show to the client). A requirement is of course that the content of the template variables should be escaped correctly in order to get valid JSON. What is the best way to do this?
The second approach is to serialize the POJO of the model directly into JSON. Of course this is faster and can be done with less effort. In contrast to the template approach, it is perhaps more reliable since it is an automatic process. BUT: how can I exclude data like password and metadata fields? should I construct a new JSON object with the jackson implementation that only contains the relevant data? Or do I have to create a "json-model" for each model class and transform the real model on each request into the json-model before I can serialize it?
Personally, I like the template approach because of its flexibility. But some of you will say, never construct JSON, XML etc. manually. But is this really a problem in this case, what would you recommend?
Assuming you're using Java, Jackson let you exclude fields using annotations. See: http://jackson.codehaus.org/1.0.0/javadoc/org/codehaus/jackson/annotate/JsonIgnore.html
I'm using xerces SAX to parse this XML:
<product id="123">
<sku>abc123</sku>
<location>
<warehouse>1</warehouse/>
<level>3</level>
</location>
<details>
<weight unit="kg">150</weight/>
<mfg>honda</mfg>
</details>
</product>
So I created my own class named ProductSAXHandler.java:
public class ProductSAXHandler extends DefaultHandler {
}
Now from my spring mvc controller I plan on pass my XML file as a string, and I want a Product object returned.
So inside my ProductSAXHandler I will create my startElement, endElement methods.
So should I just create a method that takes the xml as a string, then instantiates this ProductSAXhandler and then call parse?
This is my first time dealing with xml/sax so I'm a little unclear how to design this class.
This doesn't directly answer your question, but I'm gonna read a bit between the lines and focus on your actual intention...
Since you want an instance of some Product class that encapsulates the data from the XML, probably in a structured way by preference, you'd do much better to use JAXB for this task. Unless you have really specific requirements regarding the customization of binding XML input to objects, this will turn out a lot simpler than using SAX.
What you'll need to do is:
Get a W3C XML Schema for your XML. If you don't have one and can't obtain one, then there are tools out there that can generate a schema based on input XML. Trang makes this very easy.
Generate Java classes from the schema. For this you can use XJC (the XML-to-Java Compiler) available with Sun's JDK. If you're using build tools like Ant or Maven, there's plugins available. This can automate the process to make it part of a full build.
Use the JAXB API with your generated classes to easily turn XML documents into objects and vice-versa.
Although JAXB will take some time to learn (especially if the desired XML-Java mapping isn't 1-to-1), I think you'll end up saving time in the long run.
Sorry if you really do need SAX and this answer is not applicable, but I figured I'd rather let you know your options before using a somewhat archaic XML processing model. Note that DOM and StAX might also be of interest to you.
I've got to write a multithreaded chat program, using a server and clients but each message sent has to be in XML.
Is it simpler/easier just to write out all the code in java, and then try and somehow alter it so the messages are sent in XMl format, or would it be simpler just to try and go for it in XML and hope it works. I'll admit I don't know that much about XML. :)
Also any links to any relevant online help/tutorials would be much appreciated.
Thanks.
When messing with XML in Java, PLEASE consider using JAXB or something similar. It allows you to work with a normal object graph in memory and then serialize that to XML in one operation (and the other way around).
Manipulating XML through the DOM API is a slow way to lose your sanity, do not do it for any non-trivial amount of XML.
I fail to see what the program being multithreaded or a server have to do with it though...
Check out XStream. You can use this to marshall a normal Java object into XML, and back again into an object, without having to do anything instrusive like define interfaces or specify schema etc. i.e. it works out of the box for objects you already have defined. For most cases it's seamless in its default mode.
XStream produces a direct XML serialised representation of a Java object (i.e. XML elements represent each field of a Java object directly). You can customise this further as/when you require. If you want to define persisted objects in terms of schema (XSD) then it's not appropriate. However if you're transporting objects where persistence is short-term and you're not worried about conforming to some schema then it's definitely of use.
e.g.
Person person = new Person("Brian Agnew");
XStream xStream = new XStream();
System.out.println(xStream.toXML(person));
and conversion from XML to the Person object is similarly trivial.
(note XStream is thread-safe)
There is something called XML RPC. This examples pretty much shows what you're looking for:
http://docstore.mik.ua/orelly/xml/jxml/ch11_02.htm
It would be simpler to use existing XMPP clients and servers and not write your own at all.
If this is in fact homework, then I would suggest writing the client and server as you have suggested, using all java, but use a String as the message. You can then easily add parsing of the string to/from XML when all other parts are working.
I would suggest to also have a look at Betwixt and Digester. For Digester there are some tutorials which can be found in the Digister-wiki. Betwixt provides some pretty good tutorials right on its website.
Additionally to these two tools there is a list of alternatives that can be found in the Reference section of http://wiki.apache.org/commons/Digester/WhyUseDigester
You're on the right page trying to break the task into smaller pieces.