Reputation: 222
I have one XML which i need to convert to JSON when in XML we have more than one element its creating proper jsonArray but when single element not creating the array can any one please help me how we can get array in case of single element
String TEST_XML_STRING = "<Items><Item><Name>Stack</Name><Name>OverFlow</Name></Item></Items>";
JSONObject xmlJSONObj = XML.toJSONObject(TEST_XML_STRING);
// output - {"Items":{"Item":{"Name":["Stack","OverFlow"]}}}
when
String TEST_XML_STRING = "<Items><Item><Name>Stack</Name></Item></Items>";
JSONObject xmlJSONObj = XML.toJSONObject(TEST_XML_STRING);
// output - {"Items":{"Item":{"Name":"Stack"}}}
but it should be {"Items":{"Item":[{"Name":"Stack"}]}}
Upvotes: 4
Views: 15014
Reputation: 11
Based on Mario's solution, I made some changes, specially for nested children in the Json object. The xmlJSONObj is the same, but the obj param is a List that contains the path to the JSON child, and the index param is only required for the recursion (it should start at 0 in the first execution).
/**
* Forces a JSON Object to be an Array. When converting from XML to JSON, There may be cases in
* which we want a list of elements in the final JSON but there is only one element in the XML
* file, so the XML.toJSONObject method will fail. This methods forces a JSON element to be an
* array instead of just a JSON Object.
*
* @param xmlJSONObj obtained by passing the XML through the method toJSONObject
* @param obj list of String that contains the path to the JSON child to convert to Array
* @param index required for recursion, starts at 0
* @throws org.json.JSONException
*/
public static void forceToJSONArray(JSONObject xmlJSONObj, List<String> obj, int index)
throws org.json.JSONException {
Object myObj = xmlJSONObj.opt(obj.get(index));
if (myObj instanceof JSONObject && obj.size() == index + 1) {
JSONObject myJSONObj = (JSONObject) myObj;
JSONArray jsonArray = new JSONArray();
jsonArray.add(myJSONObj);
xmlJSONObj.put(obj.get(index), jsonArray);
} else if (myObj instanceof JSONObject) {
forceToJSONArray((JSONObject) myObj, obj, index + 1);
}
}
Example:
We have this JSON:
{
"person":{
"name":"Tony",
"data":{
"car":"Toyota"
}
}
}
And we want this JSON:
{
"person":{
"name":"Tony",
"data":{
"car":["Toyota"]
}
}
}
We should call the method like this:
forceToJSONArray(xmlJSONObj, Arrays.asList("person", "data", "car"), 0);
Upvotes: 1
Reputation: 1
It's very late to reply to this post but my solution might help someone.
Problem Description : Always convert a specific XML tag to JSON Array irrespective of number of instances.
Traditional Way : Single instance of XML tag will always converts into JSON object, We couldn't do anything here. Please find below for my solution.
My Approach : So take above point into consideration, if we always insert a dummy empty tag in the beginning just to make sure that we have more than one instance of same XML tag.
As we are adding a dummy in the beginning, If we convert this XML into JSON, we always have a null object in the 0th instance of our JSON array. So we have to remove this null object from our array using .remove(0) method of JSONArray Class.
Combining all together, Please find the sample java code for your reference.
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.XML;
public class XMLtoJSONConverter {
public static void main(String[] args) {
String xmlData = "<Items><Item><Name>Stack</Name><Name>OverFlow</Name></Item></Items>";
xmlData = xmlData.replaceFirst("<Item>","<Item/><Item>");
try {
JSONObject xmlJSONObj = XML.toJSONObject(xmlData);
JSONArray jsonArray = xmlJSONObj.getJSONObject("Items").getJSONArray("Item");
jsonArray.remove(0);
System.out.println(xmlJSONObj);
} catch (JSONException je) {
System.out.println(je.toString());
}
}
}
Output :
{
"Items":{
"Item":[{
"Name":["Stack","OverFlow"]
}]
}
}
Note : "Item" tag in the given XML is actually a single instance but it turns out to be JSON array in the output.
Happy Coding!!!
Upvotes: 0
Reputation: 171
I'm late on this... but, using org.json:
public static void forceToJSONArray(JSONObject xmlJSONObj, String obj) throws org.json.JSONException
{
// where "JSONObject xmlJSONObj" is my JSONObject obtained by passing the XML throug the method toJSONObject
// and where "String obj" is the name of the JSONObject I want to force to JSONArray
Object myObj = xmlJSONObj.opt(obj);
if (myObj == null)
{
// if my obj doesn't exist inside my xmlJSONObj i create it empty
JSONArray jsonArray = new JSONArray();
xmlJSONObj.put(obj, jsonArray);
}
else if ( myObj instanceof JSONObject )
{
// if exist but is a JSONObject, I force it to JSONArray
JSONObject myJSONObj = (JSONObject)myObj;
JSONArray jsonArray = new JSONArray();
jsonArray.put(myJSONObj);
xmlJSONObj.put(obj, jsonArray);
}
else if ( myObj instanceof String || myObj instanceof Integer )
{
// if exist but is a primitive entry (like in your case), I force it to a "primitive" JSONArray
JSONArray jsonArray = new JSONArray();
jsonArray.put(myObj);
xmlJSONObj.put(obj, jsonArray);
}
}
Hope this could help ;)
Upvotes: 2
Reputation: 81
I use these two methods, but you will have to identify which fields you want to wrap in a array. With javax.json.*:
private static JsonObject wrapFieldInArray(JsonObject object, String fieldKey) {
JsonValue fieldValue = object.get(fieldKey);
if(fieldValue instanceof JsonObject){
JsonObjectBuilder builder = Json.createObjectBuilder(object);
builder.remove(fieldKey);
builder.add(fieldKey, wrapObjectInArray((JsonObject) fieldValue));
object = builder.build();
}
return object;
}
public static JsonArray wrapObjectInArray(JsonObject obj){
JsonArrayBuilder builder = Json.createArrayBuilder();
builder.add(obj);
return builder.build();
}
And with org.json:
private static JSONObject wrapFieldInArray(JSONObject object, String fieldKey) {
Object fieldValueObj = object.get(fieldKey);
if(fieldValueObj instanceof JSONObject){
JSONObject fieldValue = (JSONObject) fieldValueObj;
object.remove(fieldKey);
object.put(fieldKey, wrapObjectInArray(fieldValue));
}
return object;
}
public static JSONArray wrapObjectInArray(JSONObject obj){
return new JSONArray().put(new JSONObject(obj.toString()));
}
Upvotes: 0
Reputation: 1590
If you are using Java 8 or later, you should check out my open source library: unXml. unXml basically maps from Xpaths to Json-attributes.
It's available on Maven Central.
Example
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.nerdforge.unxml.factory.ParsingFactory;
import com.nerdforge.unxml.parsers.Parser;
import org.w3c.dom.Document;
public class Parser {
public ObjectNode parseXml(String xml){
Parsing parsing = ParsingFactory.getInstance().create();
Document document = parsing.xml().document(xml);
Parser<ObjectNode> parser = parsing.obj("/Items/Item")
.attribute("name", "Name")
.build();
ObjectNode result = parser.apply(document);
return result;
}
}
It will return a Jackson ObjectNode
, with the following json:
{"name":"Stack"}
You can also create a parser that will return nested ObjectNodes
or ArrayNodes
to whatever JSON structure you desire.
Upvotes: 0
Reputation: 116
There doesn't seem to be out of the box way of doing that. If the json is processed in the code later on you could check whether it's JSONObject or JSONArray. In case you need to return json object in the correct format from let say spring mvc rest controller, you could also check what you dealing with (JSONArray or JSONObject). When it's JSONObject you will have to replace it with JSONArray with the same data.
Test if it is JSONObject or JSONArray
Upvotes: 0
Reputation: 5371
If XML tag has a single child, it will convert this child to an object instead of an array. But if XML tag has 2+ children of the same name, it returns an array.
You can do nothing with this. The only way is to use another library.
Upvotes: 0