Mam zamiar otrzymać obiekt JSON lub tablicę z serwera, ale nie mam pojęcia, który to będzie. Muszę pracować z JSON, ale aby to zrobić, muszę wiedzieć, czy jest to obiekt czy tablica.
W przypadku korzystania z systemu Android Gson a jeśli chodzi o deserialing jeden sposób, aby zrobić to jak ten .
pirho
Odpowiedzi:
249
Znalazłem lepszy sposób na określenie:
String data = "{ ... }";
Object json = new JSONTokener(data).nextValue();
if (json instanceof JSONObject)
//you have an objectelseif (json instanceof JSONArray)
//you have an array
dobra robota. mam nadzieję, że sprawdzi zarówno JsonObject, jak i Json Array
Shreyash Mahajan
2
@neworld, ale co, jeśli jestem w środku pętli. próba pobrania data.getJSONArray () lub data.getJSONObject () potencjalnie wyrzuci wyjątek JSONEXception !!
P-RAD
Cześć, moje dane obiektu są w połowie odpowiedzi, więc jak mogę to wykryć? sprawdzić, czy jest to JSONObject czy JSONArray ??? i W swojej odpowiedzi String data = "{...}"; ma wartość całej odpowiedzi ???
amit pandya
Aby to osiągnąć, musisz przeanalizować swój JSON przy użyciu JSONTokener. Nie zrobiłem tego, ale przypuszczam, że powinieneś pominąćPast ("twój_klucz") . Ale nie jestem pewien. Jednak powinieneś rozważyć użycie json mapper: Gson, Jackson, Moshi i mnóstwo innych.
neworld
54
Możesz to zrobić na kilka sposobów:
Możesz sprawdzić znak na pierwszej pozycji ciągu (po usunięciu białych znaków, ponieważ jest to dozwolone w prawidłowym formacie JSON). Jeśli jest to {, masz do czynienia z a JSONObject, jeśli jest to [, masz do czynienia z JSONArray.
Jeśli masz do czynienia z JSON (an Object), możesz instanceofsprawdzić. yourObject instanceof JSONObject. Zwróci to wartość true, jeśli yourObject jest JSONObject. To samo dotyczy JSONArray.
To zdecydowanie zadziałało. Ostatecznie jednak umieściłem ciąg w JSONObject i jeśli wyrzucił błąd, wiedziałem, że to JSONArray. try {return new JSONObject (json); } catch (wyjątek e) {} try {return new JSONArray (json); } catch (wyjątek e) {}
Greg
3
Twoja pierwsza opcja nie będzie działać niezawodnie, ponieważ białe znaki są dozwolone na początku danych JSON. Musisz pominąć wszelkie początkowe spacje i sprawdzić pierwszy znak niebędący białymi znakami.
user9876
1
@ user9876 Dzięki za ostrzeżenia. Zmieniono, aby odzwierciedlić Twój komentarz
nicholas.hauschild
14
Oto proste rozwiązanie, którego używam na Androidzie:
JSONObject json = new JSONObject(jsonString);
if (json.has("data")) {
JSONObject dataObject = json.optJSONObject("data");
if (dataObject != null) {
//Do things with object.
} else {
JSONArray array = json.optJSONArray("data");
//Do things with array
}
} else {
// Do nothing orthrow exception if"data"is a mandatory field
}
Nie jest specyficzna dla Androida i najbardziej podoba mi się ta wersja, ponieważ nie używa sprawdzania znaków, ale json.has("data")zakłada, że całość jest opcjonalna (nie jest wymagana).
Myślę, że pytanie zakłada, że będziesz pracować ze zwykłym ciągiem znaków, więc użycie funkcji instanceof lub getClass (). GetName () nie zadziała.
gamerson,
@gamerson - To dziwne - działało na mnie wiele razy. Wystarczy, że parser zwróci jeden z obiektów, zamiast określać który.
Hot Licks,
1
Najwyraźniej ludzie tego nie rozumieją. Prawie każdy parser, jaki widziałem, ma opcję parsowania, aby zwrócić „JSONInstance” lub po prostu „Object”, lub cokolwiek innego. Przeanalizuj JSON, a następnie zapytaj, co to jest. Parser, który nie ma tej możliwości, jest uszkodzony.
Hot Licks
(W rzeczywistości jest to mniej więcej odpowiedź Neworld.)
Hot Licks
0
Dla tych, którzy zajmują się tym problemem w JavaScript, wykonałem zadanie za mnie (nie jestem pewien, jak wydajne jest to).
Odpowiedzi:
Znalazłem lepszy sposób na określenie:
String data = "{ ... }"; Object json = new JSONTokener(data).nextValue(); if (json instanceof JSONObject) //you have an object else if (json instanceof JSONArray) //you have an array
tokenizer jest w stanie zwrócić więcej typów: http://developer.android.com/reference/org/json/JSONTokener.html#nextValue ()
źródło
JSONTokener
. Nie zrobiłem tego, ale przypuszczam, że powinieneś pominąćPast ("twój_klucz") . Ale nie jestem pewien. Jednak powinieneś rozważyć użycie json mapper: Gson, Jackson, Moshi i mnóstwo innych.Możesz to zrobić na kilka sposobów:
{
, masz do czynienia z aJSONObject
, jeśli jest to[
, masz do czynienia zJSONArray
.Object
), możeszinstanceof
sprawdzić.yourObject instanceof JSONObject
. Zwróci to wartość true, jeśli yourObject jest JSONObject. To samo dotyczy JSONArray.źródło
Oto proste rozwiązanie, którego używam na Androidzie:
JSONObject json = new JSONObject(jsonString); if (json.has("data")) { JSONObject dataObject = json.optJSONObject("data"); if (dataObject != null) { //Do things with object. } else { JSONArray array = json.optJSONArray("data"); //Do things with array } } else { // Do nothing or throw exception if "data" is a mandatory field }
źródło
json.has("data")
zakłada, że całość jest opcjonalna (nie jest wymagana).Przedstawiamy inny sposób:
if(server_response.trim().charAt(0) == '[') { Log.e("Response is : " , "JSONArray"); } else if(server_response.trim().charAt(0) == '{') { Log.e("Response is : " , "JSONObject"); }
Oto
server_response
ciąg odpowiedzi pochodzący z serweraźródło
Bardziej podstawowy sposób wykonania tego jest następujący.
JsonArray
jest z natury ListąJsonObject
jest z natury mapąif (object instanceof Map){ JSONObject jsonObject = new JSONObject(); jsonObject.putAll((Map)object); ... ... } else if (object instanceof List){ JSONArray jsonArray = new JSONArray(); jsonArray.addAll((List)object); ... ... }
źródło
wystąpienie
Object.getClass (). GetName ()
źródło
Dla tych, którzy zajmują się tym problemem w JavaScript, wykonałem zadanie za mnie (nie jestem pewien, jak wydajne jest to).
if(object.length != undefined) { console.log('Array found. Length is : ' + object.length); } else { console.log('Object found.'); }
źródło
Moje podejście byłoby całkowitą abstrakcją. Może ktoś uzna to za przydatne ...
import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collection; import java.util.Map; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; public class SimpleJSONObject extends JSONObject { private static final String FIELDNAME_NAME_VALUE_PAIRS = "nameValuePairs"; public SimpleJSONObject(String string) throws JSONException { super(string); } public SimpleJSONObject(JSONObject jsonObject) throws JSONException { super(jsonObject.toString()); } @Override public JSONObject getJSONObject(String name) throws JSONException { final JSONObject jsonObject = super.getJSONObject(name); return new SimpleJSONObject(jsonObject.toString()); } @Override public JSONArray getJSONArray(String name) throws JSONException { JSONArray jsonArray = null; try { final Map<String, Object> map = this.getKeyValueMap(); final Object value = map.get(name); jsonArray = this.evaluateJSONArray(name, value); } catch (Exception e) { throw new RuntimeException(e); } return jsonArray; } private JSONArray evaluateJSONArray(String name, final Object value) throws JSONException { JSONArray jsonArray = null; if (value instanceof JSONArray) { jsonArray = this.castToJSONArray(value); } else if (value instanceof JSONObject) { jsonArray = this.createCollectionWithOneElement(value); } else { jsonArray = super.getJSONArray(name); } return jsonArray; } private JSONArray createCollectionWithOneElement(final Object value) { final Collection<Object> collection = new ArrayList<Object>(); collection.add(value); return (JSONArray) new JSONArray(collection); } private JSONArray castToJSONArray(final Object value) { return (JSONArray) value; } private Map<String, Object> getKeyValueMap() throws NoSuchFieldException, IllegalAccessException { final Field declaredField = JSONObject.class.getDeclaredField(FIELDNAME_NAME_VALUE_PAIRS); declaredField.setAccessible(true); @SuppressWarnings("unchecked") final Map<String, Object> map = (Map<String, Object>) declaredField.get(this); return map; } }
A teraz pozbądź się tego zachowania na zawsze ...
źródło