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
CodePudding user response:
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)