【问题标题】:Parsing nested json array解析嵌套的json数组
【发布时间】:2018-03-22 13:00:54
【问题描述】:

我在从 json 文件中获取我想要的值时遇到了一些麻烦。我正在使用简单的json。它看起来像这样:

 [
  {
    "BUTT LIFT (BRIDGE)": [
      {
        "Main Muscle Worked": "Glutes",
        "Sport": "No",
        "Force": "Push",
        "Level": "Beginner",
        "mucle_heatmap": "http://assets.bodybuilding.com/images/trackers/exercise/heatmap/14.gif",
        "female_image_end": "http://www.bodybuilding.com/exercises/exerciseImages/sequences/99/Female/l/99_2.jpg",
        "female_image_start": "http://www.bodybuilding.com/exercises/exerciseImages/sequences/99/Female/l/99_1.jpg",
        "guide": [
          "Lie flat on the floor on your back with the hands by your side and your knees bent.   Your feet should be placed around shoulder width.  This will be your starting position.",
          "Pushing mainly with your heels, lift your hips off the floor while keeping your back straight.  Breathe out as you perform this part of the motion and hold at the top for a second.",
          "Slowly go back to the starting position as you breathe in."
        ],
        "male_image_start": "http://www.bodybuilding.com/exercises/exerciseImages/sequences/99/Male/l/99_1.jpg",
        "Equipment": "Body Only",
        "link": "http://www.bodybuilding.com/exercises/detail/view/name/butt-lift-bridge",
        "male_image_end": "http://www.bodybuilding.com/exercises/exerciseImages/sequences/99/Male/l/99_2.jpg",
        "Other Muscles": "Hamstrings",
        "Type": "Strength",
        "Mechanics Type": "Isolation"
      }
    ]
  },

该文件很大,包含大约 800 个练习。我想要的是映射字符串,例如“Force”、“Level”,但我不确定如何访问它。

这是我目前的代码

public void parse() {
    JSONParser parser = new JSONParser();
    try {
        Object obj = parser.parse(new FileReader(filePath));
        JSONArray exerciseList = (JSONArray) obj;

        for (int i = 0; i < exerciseList.size(); i++) {
            JSONObject jsonObj = (JSONObject) exerciseList.get(i);

        }

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ParseException e) {
        e.printStackTrace();
    }
}

这会导致获取整个 JSON 文件。

【问题讨论】:

  • TBH JSON 似乎做得不太好,这可能就是您遇到麻烦的原因。目前,您的jsonObj 将是一个对象,该对象将具有诸如"BUTT LIFT (BRIDGE)" 之类的字段,其值将是一个数组,其中包含一个具有许多字段(例如级别和力)的对象。这对于它所描述的内容来说似乎太复杂了,尽管一个更大的例子可以解释为什么需要这种复杂性。我想您需要做的下一步是通过索引访问您的jsonObj 的字段,因为它们的名称各不相同:将您的jsonObj 处理为Map 并通过getEntries 浏览其字段

标签: java json parsing


【解决方案1】:

使用 json-simple 递归遍历 JSON 并不难。这里我只关注StringLong 字段,但很明显如何添加更多字段。

public class WalkJSON {
    private static final String PATH_SEPARATOR = "/";

    /**
     * Offers the opportunity to examine fields in the JSON.
     */
    public static class FieldVisitor {
        void visit(String path, String value){};
        void visit(String path, Long value){};
    }

    /**
     * Walks the JSON structure calling the visitor for every String field in the structure.
     */
    public static void walk(String jsonString, FieldVisitor visitor) throws ParseException {
        walk(new JSONParser().parse(jsonString), "", visitor);
    }

    /**
     * Discerns which type of object it is and dispatches to the correct method.
     */
    private static void walk(Object json, String path, FieldVisitor visitor) {
        if (json instanceof JSONObject) {
            walk((JSONObject) json, path, visitor);
        } else if (json instanceof JSONArray) {
            walk((JSONArray) json, path, visitor);
        } else if (json instanceof String) {
            visitor.visit(path, (String) json);
        } else if (json instanceof Long) {
            visitor.visit(path, (Long) json);
        } else {
            System.out.println("Unknown type "+json.getClass());
        }
    }

    /**
     * Walks all keys of a JSONObject.
     */
    private static void walk(JSONObject json, String path, FieldVisitor visitor) {
        for (Object o : json.entrySet()) {
            Map.Entry<String, Object> e = (Map.Entry<String, Object>) o;
            // Visit every entry.
            walk(e.getValue(), path + PATH_SEPARATOR + e.getKey(), visitor);
        }
    }

    /**
     * Walks all entries in a JSON array.
     */
    private static void walk(JSONArray json, String path, FieldVisitor visitor) {
        for (int i = 0; i < json.size(); i++) {
            // Visit every entry.
            walk(json.get(i), path + PATH_SEPARATOR + i, visitor);
        }
    }
}

然后您可以编写自己的访问者来捕获特定字段。

    WalkJSON.walk(json, new WalkJSON.FieldVisitor() {
        @Override
        public void visit(String path, String value) {
            if(path.contains("/guide/")) {
                System.out.println(value);
            }
        }
    });

您现在需要做的就是弄清楚如何使用正则表达式或其他方式选择您要查找的字段。

【讨论】:

    【解决方案2】:

    我在这里使用org.json。通过考虑您的输入 JSON 和您给出的逗号 , 的位置,我假设 "BUTT LIFT (BRIDGE)" 将始终有一个元素。如果它的元素多于 1,我们将不得不为 BUTT LIFT (BRIDGE) 编写另一个内部循环。

    package org.home.example;
    
    import java.util.HashMap;
    
    import org.json.JSONArray;
    
    import org.json.JSONObject;
    
    public class Test {
    
    public static void main(String[] args) {
        //input arry with with two elements. It can have more elements
        String StringJson="[{\"BUTT LIFT (BRIDGE)\":[{\"Main Muscle Worked\":\"Glutes\",\"Sport\":\"No\",\"Force\":\"Push\",\"Level\":\"Beginner\",\"mucle_heatmap\":\"http://assets.bodybuilding.com/images/trackers/exercise/heatmap/14.gif\",\"female_image_end\":\"http://www.bodybuilding.com/exercises/exerciseImages/sequences/99/Female/l/99_2.jpg\",\"female_image_start\":\"http://www.bodybuilding.com/exercises/exerciseImages/sequences/99/Female/l/99_1.jpg\",\"guide\":[\"Lie flat on the floor on your back with the hands by your side and your knees bent.   Your feet should be placed around shoulder width.  This will be your starting position.\",\"Pushing mainly with your heels, lift your hips off the floor while keeping your back straight.  Breathe out as you perform this part of the motion and hold at the top for a second.\",\"Slowly go back to the starting position as you breathe in.\"],\"male_image_start\":\"http://www.bodybuilding.com/exercises/exerciseImages/sequences/99/Male/l/99_1.jpg\",\"Equipment\":\"Body Only\",\"link\":\"http://www.bodybuilding.com/exercises/detail/view/name/butt-lift-bridge\",\"male_image_end\":\"http://www.bodybuilding.com/exercises/exerciseImages/sequences/99/Male/l/99_2.jpg\",\"Other Muscles\":\"Hamstrings\",\"Type\":\"Strength\",\"Mechanics Type\":\"Isolation\"}]},{\"BUTT LIFT (BRIDGE)\":[{\"Main Muscle Worked\":\"Glutes\",\"Sport\":\"No\",\"Force\":\"Push1\",\"Level\":\"Beginner1\",\"mucle_heatmap\":\"http://assets.bodybuilding.com/images/trackers/exercise/heatmap/14.gif\",\"female_image_end\":\"http://www.bodybuilding.com/exercises/exerciseImages/sequences/99/Female/l/99_2.jpg\",\"female_image_start\":\"http://www.bodybuilding.com/exercises/exerciseImages/sequences/99/Female/l/99_1.jpg\",\"guide\":[\"Lie flat on the floor on your back with the hands by your side and your knees bent.   Your feet should be placed around shoulder width.  This will be your starting position.\",\"Pushing mainly with your heels, lift your hips off the floor while keeping your back straight.  Breathe out as you perform this part of the motion and hold at the top for a second.\",\"Slowly go back to the starting position as you breathe in.\"],\"male_image_start\":\"http://www.bodybuilding.com/exercises/exerciseImages/sequences/99/Male/l/99_1.jpg\",\"Equipment\":\"Body Only\",\"link\":\"http://www.bodybuilding.com/exercises/detail/view/name/butt-lift-bridge\",\"male_image_end\":\"http://www.bodybuilding.com/exercises/exerciseImages/sequences/99/Male/l/99_2.jpg\",\"Other Muscles\":\"Hamstrings\",\"Type\":\"Strength\",\"Mechanics Type\":\"Isolation\"}]}]";
        JSONArray object=new JSONArray(StringJson);
        HashMap<Integer,String> Force=new HashMap<Integer,String>();
        HashMap<Integer,String> Level=new HashMap<Integer,String>();
        //iterate the array
        for(int i=0;i<object.length();i++){
            JSONObject parts=object.getJSONObject(i).getJSONArray("BUTT LIFT (BRIDGE)").getJSONObject(0);
            Force.put(i, parts.getString("Force"));
            Level.put(i,parts.getString("Level"));
        }
    
        System.out.println("Force map");
        for (HashMap.Entry<Integer, String> entry : Force.entrySet())
        {
            System.out.println(entry.getKey() + "/" + entry.getValue());
        }
    
        System.out.println("Level map");
        for (HashMap.Entry<Integer, String> entry : Level.entrySet())
        {
            System.out.println(entry.getKey() + "/" + entry.getValue());
        }
    }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多