2

I converted my XML to Json successfully using the below code.

I ran into this issue, i have two different XML strings in the below program.

First one has single value for user name and the second one has two values.

first xml produces the json without Square braces.and the second xml with Square braces.

I want both of them to have square braces. Is there a way to typecast cast the username as array in output string?

Primarily, I want both of them to look like arrays in output json.

package com.java.json;

import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;
import net.sf.json.xml.XMLSerializer;

public class XmlSerializer {

public static void main(String[] args) throws Exception {
String xmlstring = "<soapenv:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ser=\"http://services.web.post.list.com\"><soapenv:Header><authInfo xsi:type=\"soap:authentication\" xmlns:soap=\"http://list.com/services/SoapRequestProcessor\"><!--You may enter the following 2 items in any order--><username xsi:type=\"xsd:string\">user@email.com</username><password xsi:type=\"xsd:string\">password</password></authInfo></soapenv:Header></soapenv:Envelope>";
//String xmlstring = "<soapenv:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ser=\"http://services.web.post.list.com\"><soapenv:Header><authInfo xsi:type=\"soap:authentication\" xmlns:soap=\"http://list.com/services/SoapRequestProcessor\"><!--You may enter the following 2 items in any order--><username xsi:type=\"xsd:string\">user@email.com</username><username xsi:type=\"xsd:string\">user@email.com</username><password xsi:type=\"xsd:string\">password</password></authInfo></soapenv:Header></soapenv:Envelope>";

JsonConfig conf =  new JsonConfig();
XMLSerializer xs = new XMLSerializer();

xs.setForceTopLevelObject(true);   
xs.setSkipWhitespace(true);
xs.setTrimSpaces(true);    
xs.setSkipNamespaces(true);
xs.setRemoveNamespacePrefixFromElements(true);

JSONObject jsonobj = (JSONObject) xs.read(xmlstring);    
String  jsonstring  = jsonobj.toString().replace("\"@", "\"");    

System.out.println(jsonstring);     

}
} 

First XML should give output like this.

{"Envelope":{"Header":{"authInfo":{"type":"soap:authentication","username":[null],"password":null}}}}

Currently it is giving like this.

{"Envelope":{"Header":{"authInfo":{"type":"soap:authentication","username":null,"password":null}}}}

The second XML in the above program is good and it gives output like this.

{"Envelope":{"Header":{"authInfo":{"type":"soap:authentication","username":[null,null],"password":null}}}}

Thanks in advance.

RAJESH
  • 404
  • 6
  • 18
  • Why do you expect single element to be serialized into an array? – xersiee Dec 02 '15 at 22:09
  • We have a down stream process after serialization, it expects username as array. That process will fail if it is not inside square braces. We do not mind if we can add these braces after serialization in cases of single valued arrays. We just need that to be coming in square braces. We can manually doit by parsing json and adding those in worst case but i am trying for a better way to define the type of Username as array in output json by some how like casting money as array and adding those braces. – RAJESH Dec 03 '15 at 15:13
  • Ok, if you really don't want to do this manually.. I think something like this may work (but I'm not 100% sure) - build class that represents your XML/JSON structure and declare username field as `List`. Then use some framework like jackson to parse your XML into instance of this class and then serialize this object to JSON. This could work (maybe with some extra config). But IMHO - effort bigger than benefit. – xersiee Dec 03 '15 at 21:22

1 Answers1

1

After a Good amount of research I found out the best way to handle the problem.

You can convert any XML to JSON without loosing the type Information and Array issue by using the code snippet below.

We need the Java POJO to convert this way like below.

By using The AuthInfo.class in below code. I am getting the JSON with proper Data Types.

You can convert any complex XML to JSON in this method.

package com.java.json;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.jaxb.XmlJaxbAnnotationIntrospector;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector;
import com.tda.trident.beb.AuthInfo;

public class XmlDoc {

public static void main(String[] args) throws Exception {
    String xmlstring = "<soapenv:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ser=\"http://services.web.post.list.com\"><soapenv:Header><authInfo xsi:type=\"soap:authentication\" xmlns:soap=\"http://list.com/services/SoapRequestProcessor\"><!--You may enter the following 2 items in any order--><username xsi:type=\"xsd:string\">user@email.com</username><password xsi:type=\"xsd:string\">password</password></authInfo></soapenv:Header></soapenv:Envelope>";
    //String xmlstring = "<soapenv:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ser=\"http://services.web.post.list.com\"><soapenv:Header><authInfo xsi:type=\"soap:authentication\" xmlns:soap=\"http://list.com/services/SoapRequestProcessor\"><!--You may enter the following 2 items in any order--><username xsi:type=\"xsd:string\">user@email.com</username><username xsi:type=\"xsd:string\">user@email.com</username><password xsi:type=\"xsd:string\">password</password></authInfo></soapenv:Header></soapenv:Envelope>";
    Object messageObj = null;       

    XmlMapper unmarshaller = new XmlMapper();
    unmarshaller.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    XmlJaxbAnnotationIntrospector xmlIntrospector = new XmlJaxbAnnotationIntrospector();
    unmarshaller.setAnnotationIntrospector(xmlIntrospector);
    JaxbAnnotationIntrospector introspector = new JaxbAnnotationIntrospector();
    ObjectMapper marshaller = new ObjectMapper().enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
    marshaller.setSerializationInclusion(Include.NON_NULL);
    marshaller.setAnnotationIntrospector(introspector);

    TransactionTradeMessage rootNode = unmarshaller.readValue(xmlstring, AuthInfo.class);

    messageObj = rootNode.getTransactionTrade();

    System.out.println(marshaller.writeValueAsString(messageObj));

}
}
RAJESH
  • 404
  • 6
  • 18
  • It is so rare to see ANY real answer to this question! Does this solution act on ALL single value objects in the XML or is there a way to target it to only act on certain nodes(xml) / values (JSON) – user1445967 Sep 05 '19 at 18:21