Как достать элементы из JSON в виде массива?

316
19 октября 2017, 09:00
"0": {},
"Guys": {
    "0": null,
    "1": {
        "id": "1",
        "name": "Mort",
        "lat": "443",
        "lng": "23",
        "status": "1"
    },
    "2": {
        "id": "2",
        "name": "Sam",
        "lat": "45",
        "lng": "324",
        "status": "0"
    },
    "3": {
        "id": "3",
        "name": "Peter",
        "lat": "546",
        "lng": "24",
        "status": "1"
    },
    "4": {
        "id": "4",
        "name": "Adam",
        "lat": "643",
        "lng": "22",
        "status": "1"
    },
    "5": {
        "id": "5",
        "name": "Bonzo",
        "lat": "2423",
        "lng": "2344",
        "status": "0"
    },
    "6": {
        "id": "6",
        "name": "hjghj",
        "lat": "657",
        "lng": "66",
        "status": "1"
    },
    "7": {
        "id": "7",
        "name": "h",
        "lat": "44",
        "lng": "44",
        "status": "0"
    },
    "8": {
        "id": "8",
        "name": "h",
        "lat": "6576",
        "lng": "6",
        "status": "1"
    },

Как вытащить все элементы из Guys(в моем случае их 8) в виде JSON массива.
Т.е... простейший, может даже и глупый пример: чтобы JSONArray.length возвращало восемь. И так, чтобы можно было доставать их в цикле и, например, выводить в List View. Спасибо.

Answer 1

Я еще не практиковал GSON (с ним удобнее) но все же:

1. Создайте модель Guy:

public class Guy {
    private long id;
    private String name;
    private double lat, lng;
    private boolean status;
    public Guy(long id, String name, double lat, double lng, boolean status){
        this.id = id;
        this.name = name;
        this.lat = lat;
        this.lng = lng;
        this.status = status;
    }
    //getters and setters
    //Alt + Insert
}

2. Парсинг JSON

public List<Guy> parseGuys(JSONObject json) {
    List<Guy> guys = new ArrayList<>();
    JSONObject guysJSON = json.getJSONObject("Guys");
    Iterator<?> keys = guysJSON.keys();
    while(keys.hasNext()) {
        Object value = guysJSON.get((String)keys.next());
        if (value != null && value instanceof JSONObject) {
            JSONObject guyJSON = (JSONObject) value;
            long id = guyJSON.getLong("id");
            String name = guyJSON.getString("name");
            double lat = guyJSON.getDouble("lat");
            double lng = guyJSON.getDouble("lng");
            boolean status = (1 == guyJSON.getInt("status"));
            guys.add(new Guy(id, name, lat, lng, status));
        }
    }
    return guys;
}

3. Создание адаптера (я предпочитаю 'RecyclerView')

public class GuysAdapter extends RecyclerView.Adapter<GuysAdapter.GuyHolder> {
    private List<Guy> guys;
    private class GuyHolder extends RecyclerView.ViewHolder {
        private TextView tv_name;
        public ViewHolder(View itemView) {
            super(itemView);
            tv_name = (TextView) itemView.findViewById(R.id.guy_item_name);
        }
        public void bind(Guy guy) {
            tv_name.setText(guy.getName());
        ]
    }
    public GuysAdapter(List<Guy> guys) {
        this.guys = guys;
    }
    @Override
    public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
        return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.guy_item, parent, false));
    }
    @Override
    public void onBindViewHolder(GuyHolder holder, int position) {
        holder.bind(guys.get(position));
    }
    @Override
    public int getItemCount() {
        return guys.size();
    }
}

4. Создание адаптера

RecyclerView guysList = (RecyclerView) findViewById(R.id.guysList);
guysList.setLayoutManager(new LinearLayoutManager(this));
GuysAdapter adapter = new GuysAdapter(parseGuys(json));
guysList.setAdapter(adapter);
Answer 2

Вообще, у вас Guys в json'е - это словарик, а не массив. С помощью jackson можно так:

ObjectMapper JsonMapper = new ObjectMapper();
ObjectNode node = JsonMapper.readValue(testStr, ObjectNode.class);
// получаем словарь парней
Map<String, ObjectNode> guys = JsonMapper.readValue(node.get("Guys"), new TypeReference<HashMap<String,ObjectNode>>() {});
// преобразуем в массив
ObjectNode[] guysArray = guys.values().toArray(new ObjectNode[guys.size()]);

Подключение jackson:

<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.9.13</version>
</dependency>
Answer 3

Допустим у вас есть модель:

public class Guy {
    public long id;
    public String name;
    public double lat, lng;
    public boolean status;
}

Так же есть класс:

public class GuysList {
    public final Map<String, Guy> guys = new HashMap<>();
    @JsonAnyGetter
    public Map<String, Object> any() {
        return guys;
    }
    @JsonAnySetter
    public void set(String name, Object value) {
        guys.put(name, value);
    }
}

Теперь вам Jackson с легкостью разберет (если вы берете json из сети - посмотрите на Retrofit + Jackson):

ObjectMapper mapper = new ObjectMapper();
GuysList data = mapper.readValue(testStr, GuysList.class);
// теперь можно вызвать data.values() для получения списка или data.size() для количества
READ ALSO
получить getSharedPreferences из Fragment

получить getSharedPreferences из Fragment

в активити есть TabLayout с ViewPager'ом, в который адаптер должен загружать 2 страницы xml

270
Android. Глюк Ripple Effect в TabLayout с FloatingActionButton

Android. Глюк Ripple Effect в TabLayout с FloatingActionButton

Имеется две вкладки, реализованные через TabLayout, ViewPager и FragmentПри отображении первой вкладки показывается кнопка FloatingActionButton

272
Set вне одного активити [требует правки]

Set вне одного активити [требует правки]

Можно ли данные из одной коллекции Set использовать в разных активити?

190
Приложение работает не на всех версиях android. Android Studio

Приложение работает не на всех версиях android. Android Studio

Запускается приложение вроде как на всем версиях андройда до API 15, как собственно и указал в манифестеНо вот есть одна проблема, когда нажимаю...

341