【问题标题】:Convert XML to Json Array when only one object Java当只有一个对象Java时将XML转换为Json Array
【发布时间】:2018-03-21 20:29:04
【问题描述】:

我有一个 XML,当在 XML 中我们有多个元素创建正确的 jsonArray 时,我需要将其转换为 JSON,但是当单个元素不创建数组时,任何人都可以帮助我如何在单个元素的情况下获取数组元素

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"]}}}

String TEST_XML_STRING = "<Items><Item><Name>Stack</Name></Item></Items>";
JSONObject xmlJSONObj = XML.toJSONObject(TEST_XML_STRING);
// output - {"Items":{"Item":{"Name":"Stack"}}}

但应该是{"Items":{"Item":[{"Name":"Stack"}]}}

【问题讨论】:

标签: java arrays json xml


【解决方案1】:

基于马里奥的解决方案,我做了一些改动,特别是针对 Json 对象中的嵌套子级。 xmlJSONObj 是一样的,但是 obj 参数是一个 List ,其中包含 JSON 子节点的路径,而 index 参数只需要递归(它应该在第一次执行时从 0 开始)。

/**
       * 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);
        }
      }

例子:

我们有这个 JSON:

{
   "person":{
      "name":"Tony",
      "data":{
         "car":"Toyota"
      }
   }
}

我们想要这个 JSON:

{
   "person":{
      "name":"Tony",
      "data":{
         "car":["Toyota"]
      }
   }
}

我们应该这样调用方法:

forceToJSONArray(xmlJSONObj, Arrays.asList("person", "data", "car"), 0);

【讨论】:

    【解决方案2】:

    回复这篇文章已经很晚了,但我的解决方案可能会对某人有所帮助。

    问题描述:总是将特定的 XML 标记转换为 JSON 数组,而不管实例的数量。

    传统方式: XML 标签的单个实例总是会转换成 JSON 对象,我们这里什么也做不了。请在下面找到我的解决方案。

    我的方法:所以请考虑以上几点,如果我们总是在开头插入一个虚拟的空标签,只是为了确保我们有多个相同的 XML 标签实例。

    由于我们在开始时添加了一个虚拟对象,如果我们将此 XML 转换为 JSON,我们的 JSON 数组的第 0 个实例中总是有一个空对象。所以我们必须使用 JSONArray 类的 .remove(0) 方法从我们的数组中移除这个空对象。

    结合在一起,请找到示例java代码供您参考。

    
        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());
              }
            }
        }
    

    输出:

    {
        "Items":{
           "Item":[{
              "Name":["Stack","OverFlow"]
            }]
         }
    }
    

    注意:给定 XML 中的“Item”标签实际上是一个实例,但在输出中却是 JSON 数组。

    编码愉快!!!

    【讨论】:

      【解决方案3】:

      我迟到了……但是,使用 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);
           }  
      }
      

      希望这会有所帮助;)

      【讨论】:

        【解决方案4】:

        我使用这两种方法,但是您必须确定要包装在数组中的字段。 使用 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();
        }
        

        还有 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()));
        }
        

        【讨论】:

          【解决方案5】:

          如果您使用的是 Java 8 或更高版本,您应该查看我的开源库:unXml。 unXml 基本上是从 Xpath 映射到 Json 属性。

          Maven Central 上可用。

          例子

          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;
            }
          }
          

          它将返回一个JacksonObjectNode,带有以下json:

          {"name":"Stack"}
          

          您还可以创建一个解析器,它将嵌套的 ObjectNodesArrayNodes 返回到您想要的任何 JSON 结构。

          【讨论】:

            【解决方案6】:

            似乎没有开箱即用的方式来做到这一点。 如果稍后在代码中处理 json,您可以检查它是 JSONObject 还是 JSONArray。如果您需要以正确的格式从 spring mvc 休息控制器返回 json 对象,您还可以检查您处理的内容(JSONArray 或 JSONObject)。当它是 JSONObject 时,您必须将其替换为具有相同数据的 JSONArray。

            Test if it is JSONObject or JSONArray

            【讨论】:

              【解决方案7】:

              如果 XML 标记只有一个子标记,它会将这个子标记转换为对象而不是数组。但如果 XML 标记有 2 个以上的同名子标记,则返回一个数组。

              你对此无能为力。唯一的方法是使用另一个库。

              【讨论】:

              • 你能推荐另一个图书馆吗?
              猜你喜欢
              • 2014-12-24
              • 1970-01-01
              • 2012-02-15
              • 1970-01-01
              • 2013-05-31
              • 2017-06-10
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多