调用方法时遇到java.lang.StackOverflowError异常

时间:2018-10-20 07:39:11

标签: java json recursion

我已经编写了一个代码,可以解析map中的JSON主体,它可以正常工作,但是当检测到JSONArray时,它会在某些迭代后引发异常。

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class JsonToMapConv {

    private static HashMap<String, Object> mapReturn = new HashMap<String, Object>();
    public static JsonParser parser = new JsonParser();

    public static void main(String[] args) throws Exception{

    String json ="{\"menu\": {\n" +
"    \"header\": \"SVG Viewer\",\n" +
"    \"items\": [\n" +
"        {\"id\": \"Open\"},\n" +
"        {\"id\": \"OpenNew\", \"label\": \"Open New\"},\n" +
"     \n" +
"        {\"id\": \"ZoomIn\", \"label\": \"Zoom In\"},\n" +
"        {\"id\": \"ZoomOut\", \"label\": \"Zoom Out\"},\n" +
"        {\"id\": \"OriginalView\", \"label\": \"Original View\"},\n" +
"       \n" +
"        {\"id\": \"Quality\"},\n" +
"        {\"id\": \"Pause\"},\n" +
"        {\"id\": \"Mute\"},\n" +
"   \n" +
"        {\"id\": \"Find\", \"label\": \"Find...\"},\n" +
"        {\"id\": \"FindAgain\", \"label\": \"Find Again\"},\n" +
"        {\"id\": \"Copy\"},\n" +
"        {\"id\": \"CopyAgain\", \"label\": \"Copy Again\"},\n" +
"        {\"id\": \"CopySVG\", \"label\": \"Copy SVG\"},\n" +
"        {\"id\": \"ViewSVG\", \"label\": \"View SVG\"},\n" +
"        {\"id\": \"ViewSource\", \"label\": \"View Source\"},\n" +
"        {\"id\": \"SaveAs\", \"label\": \"Save As\"},\n" +
"        \n" +
"        {\"id\": \"Help\"},\n" +
"        {\"id\": \"About\", \"label\": \"About Adobe CVG Viewer...\"}\n" +
"    ]\n" +
"}}";

       HashMap<String, Object> map = createHashMapFromJsonString(json,"");        
        for (Map.Entry<String, Object> entry : map.entrySet()) {            
          if(!entry.getValue().toString().contains("{"))  
                System.out.println(entry.getKey()+" : "+entry.getValue());
        }               
   }  

public static HashMap<String, Object> createHashMapFromJsonString(String json,String prefix) {

    System.out.println("prefix " + prefix);

    if(json.startsWith("[",0)){
        json = json.replace("[", "");
        json = json.replace("]", "");
        String subString = json.substring(2,7);       

        String[] parts = json.split("(?=\\{\""+subString+")");        

        for(int i=0; i< parts.length; i++ ){
            if(null != parts[i] && parts[i].length()>0){
                if(parts[i].charAt(parts[i].length() - 1)==','){                
                    System.out.println("parts[for]-"+ i+"   is "+parts[i] + "with prefix " + prefix );                
                    parts[i] = parts[i].substring(0,parts[i].length() - 1);  
                }
            createHashMapFromJsonString(parts[i], prefix+"_"+i); 
          }            
        }
    }    
    else{
        JsonObject object = (JsonObject) parser.parse(json);   
        Set<Map.Entry<String, JsonElement>> set = object.entrySet();
        Iterator<Map.Entry<String, JsonElement>> iterator = set.iterator();
        while (iterator.hasNext()) {

            Map.Entry<String, JsonElement> entry = iterator.next(); 
            String key = entry.getKey();

            if(prefix.length()!=0){
                key = prefix + "."+key;
            }

            JsonElement value = entry.getValue();
            if (null != value) {            
                if (!value.isJsonPrimitive()) {
                    if (value.isJsonObject()) {                        
                        mapReturn.put(key, createHashMapFromJsonString(value.toString(),key));
                    } else if (value.isJsonArray() && value.toString().contains(":")) {

                        List<HashMap<String, Object>> list = new ArrayList<>();
                        JsonArray array = value.getAsJsonArray();
                        if (null != array) {
                            for (JsonElement element : array) {
                                list.add(createHashMapFromJsonString(value.toString(),key));
                            }                 
                            mapReturn.put(key, list);
                        }
                    } else if (value.isJsonArray() && !value.toString().contains(":")) {                    
                        mapReturn.put(key, value.getAsJsonArray());
                    }              
                } else {
                    mapReturn.put(key, value.getAsString());
                }
            }
        }
    }
    return mapReturn;
  }
}

我遇到的异常是:

Exception in thread "main" java.lang.StackOverflowError
    at java.util.AbstractMap.toString(AbstractMap.java:547)
    at java.lang.String.valueOf(String.java:2994)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at java.util.AbstractCollection.toString(AbstractCollection.java:462)
    at java.lang.String.valueOf(String.java:2994)
    at java.lang.StringBuilder.append(StringBuilder.java:131)

我使用的示例json来自https://json.org/example.html网站。 为了测试代码,只需为json字符串重新分配所需的值即可。

1 个答案:

答案 0 :(得分:0)

其中一个地图条目的错误entry.getValue().toString()引发,因为该条目的值包含原始地图。
要查看它是哪个条目,请简单调试您的应用程序,并在调用map之后查看createHashMapFromJsonString(json,"")的值。

enter image description here


话虽如此,我强烈建议您按照问题注释中的建议使用现有的JSON解析框架
“发明轮子”毫无意义。
许多用户 长期使用的图书馆很长,与任何新编写的图书馆相比,其发生错误的可能性要小得多代码。