2017-05-24 45 views
0

我爲了得到一個博客的新聞使用Retrofit2,每條新聞都有ň練習來學習西班牙語有下面的代碼的結構:如何在模型中表示這種結構?

練習響應部分

"exercises": { 
     "number_of_exercises": 2, 
     "exercise1": { 
     "title": "Ejercicio de comprensión B.1 (Comprehension B.1)", 
     "question1": "La noticia habla...", 
     "answer1_1": "de un test para evaluar la inteligencia humana.", 
     "answer1_2": "de un descubrimiento científico relacionado con el ser humano.", 
     "answer1_3": "del descubrimiento de una nueva especie animal.", 
     "correctAnswer1": "de un descubrimiento científico relacionado con el ser humano.", 
     "question2": "Los genes identificados...", 
     "answer2_1": "pueden explicar algunos comportamientos sociales del ser humano.", 
     "answer2_2": "explican el funcionamiento completo del cerebro.", 
     "answer2_3": "están relacionados con la inteligencia.", 
     "correctAnswer2": "están relacionados con la inteligencia.", 
     "question3": "Este descubrimiento...", 
     "answer3_1": "no aportará nada a las investigaciones sobre el cerebro.", 
     "answer3_2": "podría ofrecer nuevos datos sobre el funcionamiento del cerebro.", 
     "answer3_3": "no es muy importante para la biología.", 
     "correctAnswer3": "podría ofrecer nuevos datos sobre el funcionamiento del cerebro.", 
     "question4": "Según el texto, los científicos ya saben todo sobre los procesos cognitivos.", 
     "answer4_1": "No se sabe.", 
     "answer4_2": "Verdadero.", 
     "answer4_3": "Falso.", 
     "correctAnswer4": "Falso." 
     }, 
     "exercise2": { 
     "title": "Ejercicio de vocabulario B.2 (Vocabulary B.2)", 
     "question1": "Relacionas 'cognitivo' con...", 
     "answer1_1": "la empatía.", 
     "answer1_2": "el conocimiento.", 
     "answer1_3": "una congestión.", 
     "correctAnswer1": "el conocimiento.", 
     "question2": "'Cohorte' es igual que...", 
     "answer2_1": "'conjunto'.", 
     "answer2_2": "'comprensión'.", 
     "answer2_3": "'finalización'.", 
     "correctAnswer2": "'conjunto'.", 
     "question3": "Lo contrario de 'específico' es...", 
     "answer3_1": "'genérico'.", 
     "answer3_2": "'aleatorio'.", 
     "answer3_3": "'concreto'.", 
     "correctAnswer3": "'genérico'.", 
     "question4": "El 'genoma' está relacionado con el ADN.", 
     "answer4_1": "No se sabe.", 
     "answer4_2": "Falso.", 
     "answer4_3": "Verdadero.", 
     "correctAnswer4": "Verdadero." 
     } 
    } 

由於練習次數不同(有時候是1次或更多次),我不知道如何根據他們具有的結構類型來表示他們。

你們能幫我嗎?

我已經嘗試過創建一個類,但隨着練習1子類,練習2,等...我正在尋找最好的方式來完成這一要求

+1

您JSON必須返回演習的數組,而不是屬性的變量數。 –

+0

是的,這將是偉大的@JonathanAste,但可悲的是,客戶不打算對API進行更改:-( –

+0

理想情況下,'exercise'和'questions'應該都是數組。問題對象將包含一組可能的答案 –

回答

0

試試這個:

try { 
    ArrayList<Exercise> exercises = new ArrayList<>(); 
    JSONObject json = new JSONObject(yourJson); 
    int exerciseQuantity = json.getInt("number_of_exercises"); 
    for (int i = 1; i <= exerciseQuantity; i++) { 
     Exercise e = json.get("exercise".concat(String.valueOf(i))); 
     if (e != null) { 
      exercises.add(e); 
     } 
    } 
} catch (JSONException e) { 
    e.printStackTrace(); 
} 
0

如果你正在使用Retrofit,你可能也在使用Gson。至少,Gson允許實現精彩的東西,即使是設計糟糕的JSON文檔。

首先,您可以設計適當的對象模型以便於使用。

final class ExerciseWrapper { 

    final List<Exercise> exercises; 

    ExerciseWrapper(final List<Exercise> exercises) { 
     this.exercises = exercises; 
    } 

} 
final class Exercise { 

    final String title; 
    final List<Question> questions; 

    Exercise(final String title, final List<Question> questions) { 
     this.title = title; 
     this.questions = questions; 
    } 

} 
final class Question { 

    final String question; 
    final List<String> answers; 
    final int correctAnswer; 

    Question(final String question, final List<String> answers, final int correctAnswer) { 
     this.question = question; 
     this.answers = answers; 
     this.correctAnswer = correctAnswer; 
    } 

} 

現在,定義一些接口來實現對解串器的各種策略。 這些都是微不足道的,如果您有任何類似的東西(例如,如果您使用的是Google Guava,只需使用FunctionSupplier)即可使用。

interface IFunction<T, R> { 

    R apply(T t); 

} 
interface ISupplier<T> { 

    T get(); 

} 

接下來,你要「unflatten」的,應該是陣列如果給定的JSON是精心設計的性能。 下面的extract方法嘗試迭代每個對象屬性並檢查它是否可以提取索引。 如果索引被提取,他們會嘗試確保列表大小足以適應所有元素。 一旦列表大小正常,他們會嘗試通過策略從別處獲取值。

final class Extractors { 

    private Extractors() { 
    } 

    static <R> List<R> extract(
      final JsonObject jsonObject, 
      final IFunction<? super String, Integer> scanner, 
      final IFunction<? super JsonElement, ? extends R> mapper 
    ) { 
     final List<R> list = new ArrayList<>(); 
     for (final Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) { 
      final Integer i = scanner.apply(entry.getKey()); 
      if (i != null) { 
       ensureSize(list, i,() -> null); 
       list.set(i - 1, mapper.apply(entry.getValue())); 
      } 
     } 
     return list; 
    } 

    static <R> List<List<R>> extract(
      final JsonObject jsonObject, 
      final IFunction<? super String, Integer> superScanner, 
      final IFunction<? super String, Integer> subScanner, 
      final IFunction<? super JsonElement, ? extends R> mapper 
    ) { 
     final List<List<R>> superList = new ArrayList<>(); 
     for (final Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) { 
      final Integer superI = superScanner.apply(entry.getKey()); 
      if (superI != null) { 
       final Integer subI = subScanner.apply(entry.getKey()); 
       if (subI != null) { 
        ensureSize(superList, superI, ArrayList::new); 
        final List<R> subList = superList.get(superI - 1); 
        ensureSize(subList, subI,() -> null); 
        subList.set(subI - 1, mapper.apply(entry.getValue())); 
       } 
      } 
     } 
     return superList; 
    } 

    private static <T> void ensureSize(final Collection<? super T> collection, final int size, final ISupplier<? extends T> defaultValueSupplier) { 
     while (collection.size() < size) { 
      collection.add(defaultValueSupplier.get()); 
     } 
    } 

} 

下一個類表示了幾個字符串到整數映射策略工廠方法,以便在上述extract方法中使用:

final class Scanners { 

    private Scanners() { 
    } 

    static IFunction<String, Integer> scanByPattern(final String pattern) { 
     return scanByPattern(Pattern.compile(pattern)); 
    } 

    static IFunction<String, Integer> scanByPattern(final Pattern pattern) { 
     return name -> { 
      final Matcher matcher = pattern.matcher(name); 
      if (!matcher.matches()) { 
       return null; 
      } 
      return parseInt(matcher.group(1)); 
     }; 
    } 

} 

這些都是容易的部件。 寫一個自定義的解串器可能會更復雜。

final class ExerciseJsonDeserializer 
     implements JsonDeserializer<Exercise> { 

    private static final JsonDeserializer<Exercise> exerciseJsonDeserializer = new ExerciseJsonDeserializer(); 

    private static final IFunction<String, Integer> questionScanner = scanByPattern("question(\\d+)"); 
    private static final IFunction<String, Integer> correctAnswerScanner = scanByPattern("correctAnswer(\\d+)"); 
    private static final IFunction<String, Integer> answerScanner1 = scanByPattern("answer(\\d+)_\\d+"); 
    private static final IFunction<String, Integer> answerScanner2 = scanByPattern("answer\\d+_(\\d+)"); 

    private ExerciseJsonDeserializer() { 
    } 

    static JsonDeserializer<Exercise> getExerciseJsonDeserializer() { 
     return exerciseJsonDeserializer; 
    } 

    @Override 
    public Exercise deserialize(final JsonElement jsonElement, final Type type, final JsonDeserializationContext context) 
      throws JsonParseException { 
     final JsonObject jsonObject = jsonElement.getAsJsonObject(); 
     return new Exercise(
       jsonObject.getAsJsonPrimitive("title").getAsString(), 
       mergeQuestionParts(
         extract(jsonObject, questionScanner, JsonElement::getAsString), 
         extract(jsonObject, answerScanner1, answerScanner2, JsonElement::getAsString), 
         extract(jsonObject, correctAnswerScanner, JsonElement::getAsString) 
       ) 
     ); 
    } 

    private static List<Question> mergeQuestionParts(final Iterable<String> questionTitles, final Iterable<List<String>> answers, 
      final Iterable<String> correctAnswers) { 
     final Iterator<String> questionIterator = questionTitles.iterator(); 
     final Iterator<List<String>> answerIterator = answers.iterator(); 
     final Iterator<String> correctAnswerIterator = correctAnswers.iterator(); 
     final List<Question> questions = new ArrayList<>(); 
     while (questionIterator.hasNext() && answerIterator.hasNext() && correctAnswerIterator.hasNext()) { 
      final String question = questionIterator.next(); 
      final List<String> rawAnswers = answerIterator.next(); 
      final String correctAnswer = correctAnswerIterator.next(); 
      questions.add(new Question(question, rawAnswers, rawAnswers.indexOf(correctAnswer))); 
     } 
     return questions; 
    } 
} 
final class ExerciseWrapperJsonDeserializer 
     implements JsonDeserializer<ExerciseWrapper> { 

    private static final JsonDeserializer<ExerciseWrapper> exerciseWrapperJsonDeserializer = new ExerciseWrapperJsonDeserializer(); 

    private static final IFunction<String, Integer> exerciseScanner = scanByPattern("exercise(\\d+)"); 

    private ExerciseWrapperJsonDeserializer() { 
    } 

    static JsonDeserializer<ExerciseWrapper> getExerciseWrapperJsonDeserializer() { 
     return exerciseWrapperJsonDeserializer; 
    } 

    @Override 
    public ExerciseWrapper deserialize(final JsonElement jsonElement, final Type type, final JsonDeserializationContext context) 
      throws JsonParseException { 
     final JsonObject jsonObject = jsonElement.getAsJsonObject(); 
     return new ExerciseWrapper(
       extract(jsonObject.getAsJsonObject("exercises"), exerciseScanner, je -> context.deserialize(je, Exercise.class)) 
     ); 
    } 

} 

它是如何在Java中8位的使用:

private static final Gson gson = new GsonBuilder() 
     .registerTypeAdapter(ExerciseWrapper.class, getExerciseWrapperJsonDeserializer()) 
     .registerTypeAdapter(Exercise.class, getExerciseJsonDeserializer()) 
     .setPrettyPrinting() 
     .create(); 

public static void main(final String... args) 
     throws IOException { 
    try (final JsonReader jsonReader = getPackageResourceJsonReader(Q44165271.class, "exercise.json")) { 
     final ExerciseWrapper exerciseWrapper = gson.fromJson(jsonReader, ExerciseWrapper.class); 
     exerciseWrapper.exercises.forEach(exercise -> { 
      System.out.println(exercise.title); 
      exercise.questions.forEach(question -> { 
       System.out.println("\t" + question.question); 
       question.answers.forEach(answer -> System.out.println("\t\t" + answer)); 
       System.out.println("\t" + (question.correctAnswer + 1)); 
      }); 
     }); 
     System.out.println("-----"); 
     System.out.println(gson.toJson(exerciseWrapper)); 
    } 
} 

輸出:

Ejercicio de comprensión B.1 (Comprehension B.1) 
    La noticia habla... 
     de un test para evaluar la inteligencia humana. 
     de un descubrimiento científico relacionado con el ser humano. 
     del descubrimiento de una nueva especie animal. 
    2 
    Los genes identificados... 
     pueden explicar algunos comportamientos sociales del ser humano. 
     explican el funcionamiento completo del cerebro. 
     están relacionados con la inteligencia. 
    3 
    Este descubrimiento... 
     no aportará nada a las investigaciones sobre el cerebro. 
     podría ofrecer nuevos datos sobre el funcionamiento del cerebro. 
     no es muy importante para la biología. 
    2 
    Según el texto, los científicos ya saben todo sobre los procesos cognitivos. 
     No se sabe. 
     Verdadero. 
     Falso. 
    3 
Ejercicio de vocabulario B.2 (Vocabulary B.2) 
    Relacionas 'cognitivo' con... 
     la empatía. 
     el conocimiento. 
     una congestión. 
    2 
    'Cohorte' es igual que... 
     'conjunto'. 
     'comprensión'. 
     'finalización'. 
    1 
    Lo contrario de 'específico' es... 
     'genérico'. 
     'aleatorio'. 
     'concreto'. 
    1 
    El 'genoma' está relacionado con el ADN. 
     No se sabe. 
     Falso. 
     Verdadero. 
    3 
----- 
{ 
    "exercises": [ 
    { 
     "title": "Ejercicio de comprensión B.1 (Comprehension B.1)", 
     "questions": [ 
     { 
      "question": "La noticia habla...", 
      "answers": [ 
      "de un test para evaluar la inteligencia humana.", 
      "de un descubrimiento científico relacionado con el ser humano.", 
      "del descubrimiento de una nueva especie animal." 
      ], 
      "correctAnswer": 1 
     }, 
     { 
      "question": "Los genes identificados...", 
      "answers": [ 
      "pueden explicar algunos comportamientos sociales del ser humano.", 
      "explican el funcionamiento completo del cerebro.", 
      "están relacionados con la inteligencia." 
      ], 
      "correctAnswer": 2 
     }, 
     { 
      "question": "Este descubrimiento...", 
      "answers": [ 
      "no aportará nada a las investigaciones sobre el cerebro.", 
      "podría ofrecer nuevos datos sobre el funcionamiento del cerebro.", 
      "no es muy importante para la biología." 
      ], 
      "correctAnswer": 1 
     }, 
     { 
      "question": "Según el texto, los científicos ya saben todo sobre los procesos cognitivos.", 
      "answers": [ 
      "No se sabe.", 
      "Verdadero.", 
      "Falso." 
      ], 
      "correctAnswer": 2 
     } 
     ] 
    }, 
    { 
     "title": "Ejercicio de vocabulario B.2 (Vocabulary B.2)", 
     "questions": [ 
     { 
      "question": "Relacionas \u0027cognitivo\u0027 con...", 
      "answers": [ 
      "la empatía.", 
      "el conocimiento.", 
      "una congestión." 
      ], 
      "correctAnswer": 1 
     }, 
     { 
      "question": "\u0027Cohorte\u0027 es igual que...", 
      "answers": [ 
      "\u0027conjunto\u0027.", 
      "\u0027comprensión\u0027.", 
      "\u0027finalización\u0027." 
      ], 
      "correctAnswer": 0 
     }, 
     { 
      "question": "Lo contrario de \u0027específico\u0027 es...", 
      "answers": [ 
      "\u0027genérico\u0027.", 
      "\u0027aleatorio\u0027.", 
      "\u0027concreto\u0027." 
      ], 
      "correctAnswer": 0 
     }, 
     { 
      "question": "El \u0027genoma\u0027 está relacionado con el ADN.", 
      "answers": [ 
      "No se sabe.", 
      "Falso.", 
      "Verdadero." 
      ], 
      "correctAnswer": 2 
     } 
     ] 
    } 
    ] 
}