2016-08-09 33 views
6

Jetzt schreibe ich einen allgemeinen Weg, um die JSONObject-Daten von einem Schlüssel zu bekommen.Wie soll ich es zu einer generischen Methode ändern? Jetzt muss ich den Typ jedes Mal ändern, wenn ich die Methode aufrufen.Wie ändere ich meine Methode zu einer generischen Methode?

String a= (String) ObdDeviceTool.getResultData(result, "a", String.class); 
Double b= (Double) ObdDeviceTool.getResultData(result, "b", Double.class); 
public static Object getJSONObjectData(JSONObject result,String key,Object type){ 
    if (result.containsKey(key)) { 
     if(type.equals(String.class)) 
      return result.getString(key); 
     if(type.equals(Double.class)) 
      return result.getDouble(key); 
     if(type.equals(Long.class)) 
      return result.getLong(key); 
     if(type.equals(Integer.class)) 
      return result.getInt(key); 
    } 
    return null; 
} 
+0

@ JonnyHenly, ich habe es versucht, aber es kann nicht ändern.public static T getJSONObjectData (JSONObject Ergebnis, String-Schlüssel, T-Typ) – flower

Antwort

3
private static <T> T getJSONObjectData(JSONObject result, String key, Class<T> type) 
{ 
    Object value = result.get(key); 
    return type.cast(value); 
} 

Was müssen Sie sich bewusst sein:

  • A JSONException perlt, wenn key existiert nicht in result
  • A ClassCastException perlt, wenn type nicht die reale Typ überein von value

Fühlen Sie sich frei, diese Niveaus über zu behandeln bei Bedarf.

+0

Es hat einen Fehler, wenn der Schlüsselwert ist0, result.getDouble (Schlüssel) ist OK. Aber Double.cast (0) ist falsch. – flower

+0

@flower Hum du hast Recht. Ich bin mir jedoch nicht sicher, was der beste Weg wäre, das zu lösen. Ist es akzeptabel, dass Sie den Wert als "Zahl" abrufen? Andernfalls müssen Sie bei dieser Lösung auf "0.0" setzen, wenn Sie wissen, dass Sie diesen Wert als Double erhalten. – Spotted

+0

Ja, wenn es 0 zurückgibt, aber manchmal doppelten Wert zurückgibt, kann ich Ihren Weg nicht benutzen. So benutze ich meinen alten Weg in der Frage Demo. – flower

1

JSONObject verfügt über eine Methode, die ein Objekt zurückgibt.

Integer i = (Integer) result.get("integerKey"); 
String s = (String) result.get("stringKey"); 
Double d = (Double) result.get("doubleKey"); 

result ist Ihr JSONObject-Objekt.

2

Unter der Antwort von @Spotted ein bisschen weiter, würde ich die Strategie-Muster verwenden und so etwas tun:

private static final Map<Class<?>, BiFunction<JSONObject, String, Object>> converterMap = 
    initializeMap(); 

private static Map<Class<?>, BiFunction<JSONObject, String, Object>> initializeMap() { 
    Map<Class<?>, BiFunction<JSONObject,String, Object>> map = new HashMap<>(); 
    map.put(String.class, (jsonObject, key) -> jsonObject.getString(key)); 
    map.put(Integer.class, (jsonObject, key) -> jsonObject.getInt(key)); 
    // etc. 
    return Collections.unmodifiableMap(map); 
} 

private static <T> Optional<T> getJSONObjectData(JSONObject json, String key, Class<T> type) { 

    return 
    Optional.ofNullable(converterMap.get(key)) 
    .map(bifi -> bifi.apply(json, key)) 
    .map(type::cast); 
} 

Jetzt haben Sie eine Karte von Konvertern, wo der Schlüssel der Zieltyp. Wenn für Ihren Typ ein Konverter vorhanden ist, wird dieser verwendet und Ihr Objekt wird im richtigen Typ zurückgegeben. Andernfalls wird Optional.empty() zurückgegeben.

Dies ist eine Anwendung von
Effective Java (2nd Edition) Artikel 29:
Consider typesafe heterogeneous containers.

+0

Ich mag diese Antwort für das sichere Casting, aber es kompiliert nicht. Sie sollten 'Map <..., Funktion <...>>' durch 'Map <..., BiFunction <...>>' und 'converterMap.get (key)' durch 'converterMap.get (type)' ersetzen. – Spotted

+0

@Spotted ah ja, von einer früheren Version refaktoriert und einen Platz verpasst. Vielen Dank –