Convert XML to JSON, Issue with jaxb class being used with FasterXML - java

I need to convert XML to JSON at runtime, using FasterXML and generated beans from JAXB tool xjc using the source XSD.
I am using follwing code
public static void main(String[] args) {
try {
Testing tObj=new Testing();
ObjectMapper tester=tObj.createJaxbObjectMapper();
CustomerOrderType data=tester.readValue(TEST_XML_STRING, CustomerOrderType.class);
//ObjectMapper serializr=new ObjectMapper();
//serializr.writeValue(System.out, data);
} catch (Exception je) {
System.out.println(je.toString());
}
}
public ObjectMapper createJaxbObjectMapper()
{
final ObjectMapper mapper = new ObjectMapper();
final TypeFactory typeFactory = TypeFactory.defaultInstance();
final AnnotationIntrospector introspector = new JaxbAnnotationIntrospector(typeFactory);
// make deserializer use JAXB annotations (only)
mapper.getDeserializationConfig().with(introspector);
// make serializer use JAXB annotations (only)
mapper.getSerializationConfig().with(introspector);
return mapper;
}
But I am getting an error as follows.
com.fasterxml.jackson.core.JsonParseException: Unexpected character ('<' (code 60)): expected a valid value (number, String, array, object, 'true', 'false' or 'null')
at [Source: (String)"<ns1:orderDetail xmlns:ns1="http://www.colt.net/xml/ns/webservice/manord/v1.0"><ns7:Customer_Order_Status xmlns:ns7="http://www.colt.net/xml/ns/cbe/ord/v1.0">New</ns7:Customer_Order_Status><ns8:Order_Creation_Date xmlns:ns8="http://www.colt.net/xml/ns/cbe/ord/v1.0">2018-03-06T09:03:25</ns8:Order_Creation_Date><ns9:Opportunity_Number xmlns:ns9="http://www.colt.net/xml/ns/cbe/ord/v1.0">8798</ns9:Opportunity_Number><ns10:Order_Source xmlns:ns10="http://www.colt.net/xml/ns/cbe/ord/v1.0">eOrder Lite<"[truncated 9232 chars]; line: 1, column: 2]

It looks that you are using JSON-java lib, which is extremely lightweight and does not provide a possibility to skip namespaces from parsed XML tag names.
But this can be achieved using a more advanced XML/JSON processing lib, for example, FasterXML/Jackson.
Update
To convert String xml to Json:
1) Use com.fasterxml.jackson.dataformat:jackson-dataformat-xml lib dependency.
2) Conversion sequence is similar to:
XmlMapper xmlMapper = new XmlMapper();
MyObject myObj = xmlMapper.readValue(xml, MyObject.class);
ObjectMapper jsonMapper = new ObjectMapper();
String json = jsonMapper.writeValueAsString(myObj);
System.out.println(json);

An off-the-shelf XML-to-JSON converter is never going to give you optimal output for your particular application. You generally need to apply either some preprocessing (an XML transformation using XSLT) or some post-processing of the JSON.
In this case I would suggest doing an XSLT transformation to drop the namespaces.

Related

Why parsing Invalid json returns Empty Object [duplicate]

I need GSON mapper to throw an exception if json contains unknown fields. For example if we have POJO like
public class MyClass {
String name;
}
and json like
{
"name": "John",
"age": 30
}
I want to get some sort of message that json contains unknown field (age) that can not be deserialized.
I know there is out-of-box solution in Jackson mapper, but in our project we have been using Gson as a mapper for several years and using Jackson ends up in conflicts and bugs in different parts of project, so it is easier for me to write my own solution than using Jackson.
In other words, I want to know if there is some equivalent to Jackson's DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES in Gson. Or maybe if it can be done using Gson's DeserializationStrategy other than using reflections
I believe you cannot do it automatically with Gson.
I had to do this in a project at work. I did the following:
Gson GSON = new GsonBuilder().create();
(static final) Map<String, Field> FIELDS = Arrays.stream(MyClass.class.getDeclaredFields())
.collect(Collectors.toMap(Field::getName, Function.identity()));
JsonObject object = (JsonObject) GSON.fromJson(json, JsonObject.class);
List<String> objectProperties = object.entrySet().stream().map(Entry::getKey).collect(Collectors.toList());
List<String> classFieldNames = new ArrayList<>(FIELDS.keySet());
if (!classFieldNames.containsAll(objectProperties)) {
List<String> invalidProperties = new ArrayList<>(objectProperties);
invalidProperties.removeAll(classFieldNames);
throw new RuntimeException("Invalid fields: " + invalidProperties);
}

How to make GSON fail on unknown properties

I need GSON mapper to throw an exception if json contains unknown fields. For example if we have POJO like
public class MyClass {
String name;
}
and json like
{
"name": "John",
"age": 30
}
I want to get some sort of message that json contains unknown field (age) that can not be deserialized.
I know there is out-of-box solution in Jackson mapper, but in our project we have been using Gson as a mapper for several years and using Jackson ends up in conflicts and bugs in different parts of project, so it is easier for me to write my own solution than using Jackson.
In other words, I want to know if there is some equivalent to Jackson's DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES in Gson. Or maybe if it can be done using Gson's DeserializationStrategy other than using reflections
I believe you cannot do it automatically with Gson.
I had to do this in a project at work. I did the following:
Gson GSON = new GsonBuilder().create();
(static final) Map<String, Field> FIELDS = Arrays.stream(MyClass.class.getDeclaredFields())
.collect(Collectors.toMap(Field::getName, Function.identity()));
JsonObject object = (JsonObject) GSON.fromJson(json, JsonObject.class);
List<String> objectProperties = object.entrySet().stream().map(Entry::getKey).collect(Collectors.toList());
List<String> classFieldNames = new ArrayList<>(FIELDS.keySet());
if (!classFieldNames.containsAll(objectProperties)) {
List<String> invalidProperties = new ArrayList<>(objectProperties);
invalidProperties.removeAll(classFieldNames);
throw new RuntimeException("Invalid fields: " + invalidProperties);
}

unable to parse json using objectMapper of jackson where json value contains \\

I am de serializing json string to plain java object using jackson's ObjectMapper class. ObjectMapper is throwing an exception
json string I am trying to deserialize is
String input="{\"id\":\"30329\",\"appId\":\"3301\",\"nodeId\":1556537156187,\"data\":\"select id,obt_marks,'\\\\m' as dummy from ltc_test_1\"}";
value for data key contains \ which is causing the problem, is their a way to escape this. i want this value as is in my POJO
It can work by replacing each occurrence of \ with \\ so string will look like
\"data\":\"select id,obt_marks,'\\\\m' as dummy from ltc_test_1\"
Question: How this can be achieved using java,is there any setting in objectMapper or Jackson to tackle this problem ?
Below is pojo which i will get after de-serialization
public class WorkflowProcessInfo {
private Long id;
private Long appId;
private Long nodeId;
private String data;
}
////Code I am using for deserialization
ObjectMapper mapper = new ObjectMapper();
mapper.configure(Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, false);
mapper.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
mapper.configure(Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
mapper.configure(Feature.ALLOW_SINGLE_QUOTES, true); mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY,
true);
mapper.setSerializationInclusion(Include.NON_NULL);
try{
return mapper.readValue(inputJson, WorkflowProcessInfo.class);
}catch(Exception e){
syso(e.getMessage())}
I expecting WorkflowProcessInfo object with values as present in json meaning, data attribute of pojo should look like below
WorkflowProcessInfo.data="select id,obt_marks,'\\m' as dummy from ltc_test_1"
instead i am getting below exception
com.fasterxml.jackson.core.JsonParseException: Unrecognized character
escape 'm' (code 109) at [Source: java.io.StringReader#1ea9f6af;
line: 1, column: 84]

Convert nested JSON string to list of java object

I have this json String
{"data":"[Level [key=LevelKey [keyEnd=0], Description=abc], Level [key=levelKey [keyEnd=1], Description=xyz]", "id":"123"}
And corresponding java classes are
public class Level {
public LevelKey key;
public String id;
}
public class LevelKey{
public String keyEnd;
}
I want to convert this data json string to list of Level object using Jackson
ObjectMapper mapper = new ObjectMapper();
List<Level> arr = mapper.readValue(data, new TypeReference<List<Level>>(){});
But I am getting below error
com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'Level': was expecting ('true', 'false' or 'null')
Is there any other method to parse it?
The below does not look like a proper JSON for the purpose (except for a standard fixed string)
"[Level [key=LevelKey [keyEnd=0], Description=abc], Level [key=levelKey [keyEnd=1], Description=xyz]"
You could correct the data part of your JSON to something like below (Closest to your JSON in question) :
[\"Level [key=LevelKey [keyEnd=0], Description=abc]\",\" Level [key=levelKey [keyEnd=1], Description=xyz]\"]
Is there any other method to parse it?
You could use a direct class reference of ArrayList instead of having to instantiate TypeReference like below to parse the above (corrected) json string :
List<Level> arr = mapper.readValue(data, (new ArrayList<Level>()).getClass());
This was an interesting one I must say. Take a look at code snippet I think I got it correct :
String data ="{\"data\":\"[Level [key=LevelKey [keyEnd=0], Description=abc], Level [key=levelKey [keyEnd=1], Description=xyz]\", \"id\":\"123\"}";
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
List<Level> arr = mapper.readValue(data, (new ArrayList<Level>()).getClass());
System.out.println(arr);
I got the following output :
[{data=[Level [key=LevelKey [keyEnd=0], Description=abc], Level [key=levelKey [keyEnd=1], Description=xyz], id=123}]
Also if you encountered any JsonParseException which according to documentation means :
Exception type for parsing problems, used when non-well-formed content
(content that does not conform to JSON syntax as per specification) is
encountered.
So while hacking the JSON you can update the ObjectMapper object like this :
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
Also as mentioned by Exception_al using a direct class reference of ArrayList instead of having to instantiate TypeReference like below to parse the above (corrected) json string.
List<Level> arr = mapper.readValue(data, (new ArrayList<Level>()).getClass());
Hope this helped.
The String is not the JSON representation of what you expect you get deserialized into JAVA.
This is a JSON String:
"{"data":[{"key":{"keyEnd":0},"Description":"abc"},{"key":{"keyEnd":1},"Description":"abc"}],"id":"123"}"
So, there is either a problem with the String or you need to do the parsing yourself.

How to disable character escaping by jackson

I want to include html in my JSON response.
MyClass obj= new MyCLass();
obj.setHTML("<div style='display:none'>4</div>");
ObjectMapper mapper=new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
String jsonResponse=mapper.writeValueAsString(obj);
System.out.println(jsonResponse);
O/P i get
{"html":"<div style=\"display:none\">4</div>"}
Required O/P
{"html":"<div style='display:none'>4</div>"}
Since I want to use the json response directly. Can i disable the escaping of qoutes by object mapper.
You can annotate your getHtml method with
#JsonRawValue

Categories