2017-09-22 4 views
0

Ich habe eine JSON-Antwort, die wie folgt aussieht:Wie dynamisch benannte JSonarray mit Gson und Retrofit2 analysieren?

 { 
    "equipment_layer": [ 
     { 
      "id": 2, 
      "name": "Gateway", 
      "detail": "All gateways" 
     }, 
     { 
      "id": 3, 
      "name": "Node", 
      "detail": "All Nodes" 
     }, 
     { 
      "id": 1, 
      "name": "Miscellaneous", 
      "detail": "All miscellaneous assets" 
     }, 
     { 
      "id": 4, 
      "name": "Sensors", 
      "detail": "All Sensors" 
     }, 
     { 
      "id": 5, 
      "name": "IRM", 
      "detail": "Installation required material" 
     }, 
     { 
      "id": 6, 
      "name": "Communication", 
      "detail": "All communication devices such as Cellular Router, ETU etc. which are purely communication" 
     } 
    ], 
    "data": { 
     "1": [ 
      { 
       "equipment_id": 353, 
       "item_quantity": 1, 
       "name": "DC Current Transformer (20mm) (Old)", 
       "shortcode": "SNS-DCI-CT20m-R1A", 
       "part_number": "718,804,805,", 
       "equipment_layer_id": 1, 
       "equipment_layer_name": "Miscellaneous" 
      }, 
      { 
       "equipment_id": 357, 
       "item_quantity": 1, 
       "name": "Fuel Sensor - B4 (Old)", 
       "shortcode": "SNS-FUL-PSR-R1A", 
       "part_number": "718,810,811", 
       "equipment_layer_id": 1, 
       "equipment_layer_name": "Miscellaneous" 
      } 
     ], 
     "2": [ 
      { 
       "equipment_id": 345, 
       "item_quantity": 1, 
       "name": "RTU (Old)", 
       "shortcode": "RAN-RTU-PMCL-R1A", 
       "part_number": "787,788,789", 
       "equipment_layer_id": 2, 
       "equipment_layer_name": "Gateway" 
      } 
     ], 
     "3": [ 
      { 
       "equipment_id": 356, 
       "item_quantity": 1, 
       "name": "Battery Analyzer (Product) (Old)", 
       "shortcode": "RAN-BAM-PMCL-R1A", 
       "part_number": "787,808,809", 
       "equipment_layer_id": 3, 
       "equipment_layer_name": "Node" 
      } 
     ], 
     "4": [ 
      { 
       "equipment_id": 346, 
       "item_quantity": 1, 
       "name": "DC Current Transformer (30mm) (Old)", 
       "shortcode": "SNS-CT-DCI-R1A", 
       "part_number": "718,792,793", 
       "equipment_layer_id": 4, 
       "equipment_layer_name": "Sensors" 
      }, 
      { 
       "equipment_id": 350, 
       "item_quantity": 1, 
       "name": "AC Block CT (Old)", 
       "shortcode": "SNS-ACI-BLK-R1A", 
       "part_number": "718,790,791", 
       "equipment_layer_id": 4, 
       "equipment_layer_name": "Sensors" 
      } 
     ] 
    } 
} 

nun der Teil nach den „Daten“ Label ist dynamisch, in einer Reaktion, die ich Sub-Arrays von „1“, „2“, aber nicht von haben kann "3" oder "4". Das POJO der Daten im Inneren ist das gleiche wie Sie sehen können. Wie kann ich diese Daten analysieren? Ich benutze Rerofit2 mit Gson.converterfactory. Ich habe jsonchema2pojo auch versucht, aber die Daten innerhalb des "Daten" Gegenstandes werden nicht angezeigt.

Ich habe versucht, diese Methode zu folgen: Parsing Retrofit2 result using Gson with different JSON structures, aber ich kann nicht scheinen, den UnrwapConverter auszulösen. Dies ist meine converterfactory Umsetzung:

internal class UnwrappingGsonConverterFactory private constructor(private val gson: Gson) : Converter.Factory() { 

override fun responseBodyConverter(type: Type, annotations: Array<Annotation>, retrofit: Retrofit): Converter<ResponseBody, *> ?{ 
    if (!needsUnwrapping(annotations)) { 
     return super.responseBodyConverter(type, annotations, retrofit) 
    } 
    val typeAdapter = gson.getAdapter(TypeToken.get(type)) 
    return UnwrappingResponseConverter(typeAdapter) 
} 

private class UnwrappingResponseConverter (private val typeAdapter: TypeAdapter<*>) : Converter<ResponseBody, Any> , AnkoLogger{ 

    @Throws(IOException::class) 
    override fun convert(responseBody: ResponseBody): Any? { 
     responseBody.use { responseBody -> 
      JsonReader(responseBody.charStream()).use({ jsonReader -> 
       // Checking if the JSON document current value is null 
       val token = jsonReader.peek() 
       if (token === JsonToken.NULL) { 
        return null 
       } 
       // If it's an object, expect `{` 
       jsonReader.beginObject() 
       var value: Any? = null 
       // And iterate over all properties 
       while (jsonReader.hasNext()) { 
        val data = jsonReader.nextName() 
        debug("Unwrap Stuff: $data") 
        when (data) { 
         "1", "2", "3", "4", "5", "6" -> value = typeAdapter.read(jsonReader) 

         else ->jsonReader.skipValue() 
        } 
       } 
       // Consume the object end `}` 
       jsonReader.endObject() 
       return value 
      }) 
     } 
    } 

} 

companion object { 

    fun create(gson: Gson): Converter.Factory { 
     return UnwrappingGsonConverterFactory(gson) 
    } 

    private fun needsUnwrapping(annotations: Array<Annotation>): Boolean { 
     for (annotation in annotations) { 
      if (annotation is Unwrap) { 
       return true 
      } 
     } 
     return false 
    } 
} 

} 

Und die Schnittstelle:

@Retention(AnnotationRetention.RUNTIME) 
    @Target(AnnotationTarget.FUNCTION) 
    annotation class Unwrap 

Meine Datenklassen sind diese:

data class ActivityNodes(@SerializedName("equipment_layer") val equipmentLayer: List<EquipmentLayer>, 
         @SerializedName("data") val data: nodeData) 

data class nodeData (@SerializedName("1") val nodeList: List<dataItem>) <-- this is where I need someway to tell SerializedName that the value can be anything from 1 to 6 

data class dataItem(@SerializedName("equipment_id") val equipmentId: Int, 
        @SerializedName("item_quantity") val itemQuantity: Int, 
        @SerializedName("name") val name: String, 
        @SerializedName("shortcode") val shortCode: String, 
        @SerializedName("part_number") val partNumber: String, 
        @SerializedName("equipment_layer_id") val equipmentLayerId: Int, 
        @SerializedName("equipment_layer_name") val equipmentLayerName: String, 
        var isScanned: Boolean = false) 



data class EquipmentLayer(@SerializedName("id") val id: Int, 
          @SerializedName("name") val name: String, 
          @SerializedName("detail") val details: String) 
+0

helfen Sie, den Code setzen sollten, die Sie – joao86

Antwort

0

Verwendung unten für den Teil "Daten" von json:

Type mapType = new TypeToken<Map<String, List<EqupmentDetail.class>>>() {}.getType(); // define generic type 
Map<String, List<EqupmentDetail.class>> result= gson.fromJson(new InputStreamReader(source), mapType); 

hier definieren EqipmentDetails Klasse gleiche wie Ihr refence

definitiv

+0

So implementiert haben, müssen ich einen benutzerdefinierten Deserializer schreiben? nicht eine converterfactory – ibraizQ9

+0

wo sollte ich diese Zeilen hinzufügen? in einem Deserializer oder der Konverterfabrik? – ibraizQ9

0

Für die dynamische JSON arbeiten, müssen Sie manuell die JSON-Zeichenfolge analysieren. Um die JSON-Zeichenfolge von Retrofit zu erhalten, müssen Sie ScalarsConverterFactory statt GsonConverterFactory verwenden.

diese Abhängigkeit hinzufügen:

compile 'com.squareup.retrofit2:converter-scalars:2.3.0' 

Adapter wie folgt erstellen:

Retrofit retrofit = new Retrofit.Builder() 
    .baseUrl("http://echo.jsontest.com") 
    .addConverterFactory(ScalarsConverterFactory.create()) 
    .build() 

Anfrage Methode erstellen mit ResponseBody

public interface MyService { 
    @GET("/key/value/one/two") 
    Call<ResponseBody> getData(); 
} 

Sie können JSON-String wie diese:

MyService service = retrofit.create(MyService.class); 
Call<ResponseBody> result = service.getData(); 
result.enqueue(new Callback<ResponseBody>() { 
    @Override 
    public void onResponse(Response<ResponseBody> response) { 
     try { 
      System.out.println(response.body().string()); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    @Override 
    public void onFailure(Throwable t) { 
     e.printStackTrace(); 
    } 
}); 

Jetzt müssen Sie die JSON-Zeichenfolge manuell analysieren, um Ihre Daten von JSON zu erhalten.

Hope it :)

Verwandte Themen