Issue
I am writing a servlet program, which aim to accept both xml and json, my request in json is this,
{"Symbol":["OLM","ASC"]}
and it is working well.
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
Connection connection = null;
BufferedReader reader1 = request.getReader();
StringBuffer jb = new StringBuffer();
String line = null;
while ((line = reader1.readLine()) != null) {
jb.append(line);
}
String str = jb.toString();
JSONObject obj2 = null;
try {
obj2 = new JSONObject(str);
} catch (JSONException e1) {
e1.printStackTrace();
}
JSONArray array = null;
try {
array = (JSONArray) obj2.get("Symbol");
} catch (JSONException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
I know that it is working for json because of I am casting the obtained string(in my case str) to JSONObject, but if I want to accept XML also and obtain Symbol from it, how to change this code? Thanks in advance
Iam updating my question,
ObjectMapper objectMapper = new ObjectMapper();
if(request.getHeader("content-type")=="application/json") {
System.out.println("json ");
Symbol symbolContainerFromJson = objectMapper.readValue(request.getReader(), Symbol.class);
System.out.println(symbolContainerFromJson.getSymbolName());
}
else if (request.getHeader("content-type")=="application/xml") {
System.out.println("xml");
Symbol symbolContainerFromXml = new XmlMapper().readValue(request.getReader(), Symbol.class);
System.out.println(symbolContainerFromXml.getSymbolName());
}
But it is not entering both the loops, kindly help
Solution
The most robust way to deserialize is by creating the data structure in the back-end and let a framework like Jackson do the heavy lifting.
So we first create our object representation that we expect in either XML or JSON. No magic, it's just a POJO. I add a JsonProperty annotation because you expect Symbol upper-case and I hate upper-case fields in Java.
public class SymbolContainer {
@JsonProperty("Symbol")
private List<String> symbol;
public List<String> getSymbol() {
return symbol;
}
}
Then I use a Jackson Object/Xml mapper to transform the content from the request body to an in-memory object.
if(contentTypeIsJson(request.getHeader("content-type"))) {
SymbolContainer symbolContainerFromJson = new ObjectMapper().readValue("{\"Symbol\":[\"OLM\",\"ASC\"]}", SymbolContainer.class);
System.out.println(symbolContainerFromJson.getSymbol()); // [OLM, ASC]
} else if (contentTypeIsXml(request.getHeader("content-type"))) {
SymbolContainer symbolContainerFromXml = new XmlMapper().readValue("<root>\n" +
" <Symbol>\n" +
" <element>OLM</element>\n" +
" <element>ASC</element>\n" +
" </Symbol>\n" +
"</root>", SymbolContainer.class);
System.out.println(symbolContainerFromXml.getSymbol()); // [OLM, ASC]
}
This using only these three Jackson dependencies
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.9.5</version>
</dependency>
Note that these ObjectMappers can be configured. If you are only interested in a part of the request (eg Symbol) and want to ignore the rest of the passed object, best to configure your ObjectMapper like so, which lets you ignore unmapped fields.
new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
Answered By - Nico Van Belle
Answer Checked By - Candace Johnson (JavaFixing Volunteer)