【问题标题】:How to serialize strings and sub-array (object?) of strings gson如何序列化字符串gson的字符串和子数组(对象?)
【发布时间】:2020-04-05 21:09:16
【问题描述】:

初学者!

我有一个测验应用程序full code on Github,它加载了一个带有来自json 的四个参数的List(数据以前存储在xml 中):

  1. 问题
  2. 图片
  3. radioGroup(子列表)中提供了四个可能的答案
  4. 正确答案
   [{
        "question": "Who is the 'Modern Love' rock star singer?",
        "imageUrl": "https://postimg.cc/2VL1Y1jd",
        "answerOptions": [{
            "1": "Jaimie Hendrix",
            "2": "David Bowie",
            "3": "Jim Morrison",
            "4": "Elvis Presley"
        }],
        "correctAnswer": "David Bowie"
    }]

我收到了错误

java.lang.IllegalStateException:应为字符串,但在第 1 行第 118 列路径 $[0].answerOptions[0]

处为 BEGIN_OBJECT

那是因为我已经将所有请求的数据类型声明为字符串,而显然我有一个混合类型的数组(一个对象和一个数组):

@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
     if (response.isSuccessful()) {
          String string = response.body().string();
          Gson gson = new Gson();
          Type type = new TypeToken<List<Quiz>>(){}.getType();
          List<Quiz> list = gson.fromJson(string, type);

          // Save to database
          for (int i = 0; i < list.size(); i++) {
              Quiz quiz = list.get(i);
              quiz.save();
          }
...

我可以在桥接类中实现解决方案here

class Quiz extends LitePalSupport {
    String question;
    String imageUrl;
    String [] answerOptions;
    String correctAnswer;

    Quiz(String question, String imageUrl, String [] answerOptions, String correctAnswer) {
        this.question = question;
        this.imageUrl = imageUrl;
        this.answerOptions = answerOptions;
        this.correctAnswer = correctAnswer;
    }
}

但这意味着我将向适配器视图持有者发送一个子类,它期待String []

...
quizHolder.createRadioButtons(quiz.answerOptions);
...
void createRadioButtons(String[] answerOptions) {
    if (radioGroup.getChildAt(0) != null)
        radioGroup.removeAllViews();
    for (String s : answerOptions) {
        radioGroup.addView(createRadioButtonAnswerAndSetOnClickListener(s));
    }
}
...

有没有一种方法可以在不创建子类的情况下从 json 获取子列表?


编辑:

在@andy-turner 推荐的更改之后,我收到了错误:

org.litepal.exceptions.LitePalSupportException:尝试在空对象引用上调用虚拟方法 'java.lang.Class[] java.lang.reflect.Constructor.getParameterTypes()'

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.celebrityquiz, PID: 6493
    org.litepal.exceptions.LitePalSupportException: Attempt to invoke virtual method 'java.lang.Class[] java.lang.reflect.Constructor.getParameterTypes()' on a null object reference
        at org.litepal.crud.DataHandler.query(DataHandler.java:154)
        at org.litepal.crud.QueryHandler.onFindAll(QueryHandler.java:123)
        at org.litepal.Operator.findAll(Operator.java:1117)
        at org.litepal.Operator.findAll(Operator.java:1082)
        at org.litepal.LitePal.findAll(LitePal.java:798)
        at com.example.celebrityquiz.MainActivity$1$2.run(MainActivity.java:115)
        at android.os.Handler.handleCallback(Handler.java:751)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6077)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
...

可能在我尝试从数据库中获取数据时调用:

List<Quiz> list = LitePal.findAll(Quiz.class);

answerOptions 列也没有显示

【问题讨论】:

    标签: java object gson


    【解决方案1】:

    answerOptions 应为String[],但您已将其指定为Object[](因为{}):

        "answerOptions": [{
            ...
        }],
    

    使它成为一个字符串数组:

        "answerOptions": [
            "Jaimie Hendrix",
            "David Bowie",
            "Jim Morrison",
            "Elvis Presley"
        ],
    

    PS - "Jimi",而不是“Jaimie”。

    【讨论】:

      【解决方案2】:

      我的建议

      -> 将 Json 替换 List (Objects or Map) 改为 List Strings

      package pl.jac.mija.gson;
      
      import com.google.gson.Gson;
      import com.google.gson.reflect.TypeToken;
      import org.jetbrains.annotations.NotNull;
      import org.junit.Test;
      
      import java.lang.reflect.Type;
      import java.util.Arrays;
      import java.util.List;
      
      import static org.junit.Assert.assertEquals;
      
      public class QuizTestChangeJson {
        @Test
        public void changeJson() {
          //given
          String json = getNewJsonOneProposeOptions();
          Type type = new TypeToken<List<Quiz>>() {
          }.getType();
          //when
          List<Quiz> list = new Gson().fromJson(json, type);
          //then
          assertEquals(1, list.size());
          String correctAnswer = list.get(0).correctAnswer;
          assertEquals(correctAnswer, list.get(0).answerOptions[1]);
          assertEquals(1, Arrays.asList(list.get(0).answerOptions).indexOf(correctAnswer)); // key is string
        }
      
        @NotNull
        private String getNewJsonOneProposeOptions() {
          return "   [{\n" +
                  "        \"question\": \"Who is the 'Modern Love' rock star singer?\",\n" +
                  "        \"imageUrl\": \"https://postimg.cc/2VL1Y1jd\",\n" +
                  "        \"answerOptions\": [\n" +
                  "             \"Jaimie Hendrix\",\n" +
                  "             \"David Bowie\",\n" +
                  "             \"Jim Morrison\",\n" +
                  "             \"Elvis Presley\"\n" +
                  "        ],\n" +
                  "        \"correctAnswer\": \"David Bowie\"\n" +
                  "    }]";
        }
      }
      
      class Quiz {
        String question;
        String imageUrl;
        String[] answerOptions;
        String correctAnswer;
      }
      

      将模型测验更改为 Json

      第一个版本是带键 String -> QuizV2_String

      第二个版本是长键 -> QuizV2_Long

      我添加了一个测试来拉出正确的答案键

       package pl.jac.mija.gson;
      
      import com.google.gson.Gson;
      import com.google.gson.reflect.TypeToken;
      import org.jetbrains.annotations.NotNull;
      import org.junit.Test;
      
      import java.lang.reflect.Type;
      import java.util.List;
      import java.util.Map;
      
      import static org.junit.Assert.assertEquals;
      
      public class QuizTestChangeModel {
        @Test
        public void changeModelQuizKeyString() {
          //given
          String json = getJsonOriginal();
          Type type = new TypeToken<List<QuizV2_String>>() {
          }.getType();
          //when
          List<QuizV2_String> list = new Gson().fromJson(json, type);
          //then
          assertEquals(1, list.size());
          assertEquals("David Bowie", list.get(0).answerOptions.get(0).get("2")); // key is string
        }
      
        @Test
        public void changeModelQuizKeyLong() {
          //given
          String json = getJsonOriginal();
          Type type = new TypeToken<List<QuizV2_Long>>() {
          }.getType();
          //when
          List<QuizV2_Long> list = new Gson().fromJson(json, type);
          //then
          assertEquals(1, list.size());
          assertEquals("David Bowie", list.get(0).answerOptions.get(0).get(2L)); // key is string
        }
      
        @Test
        public void changeModelQuizFindAnswer() {
          //given
          String json = getJsonOriginal();
          Type type = new TypeToken<List<QuizV2_String>>() {
          }.getType();
          //when
          List<QuizV2_String> list = new Gson().fromJson(json, type);
          //then
          String correctAnswer = list.get(0).correctAnswer;
          String key = list.get(0).answerOptions.get(0).entrySet().stream().filter(x -> correctAnswer.equals(x.getValue())).map(Map.Entry::getKey).findFirst().orElse(null);
          assertEquals("2", key);
          assertEquals("David Bowie", list.get(0).answerOptions.get(0).get(key));
        }
      
        @NotNull
        private String getJsonOriginal() {
          return "   [{\n" +
                  "        \"question\": \"Who is the 'Modern Love' rock star singer?\",\n" +
                  "        \"imageUrl\": \"https://postimg.cc/2VL1Y1jd\",\n" +
                  "        \"answerOptions\": [{\n" +
                  "            \"1\": \"Jaimie Hendrix\",\n" +
                  "            \"2\": \"David Bowie\",\n" +
                  "            \"3\": \"Jim Morrison\",\n" +
                  "            \"4\": \"Elvis Presley\"\n" +
                  "        }],\n" +
                  "        \"correctAnswer\": \"David Bowie\"\n" +
                  "    }]";
        }
      }
      
      
      class QuizV2_String {
        String question;
        String imageUrl;
        List<Map<String, String>> answerOptions;
        String correctAnswer;
      }
      
      class QuizV2_Long {
        String question;
        String imageUrl;
        List<Map<Long, String>> answerOptions;
        String correctAnswer;
      }
      

      【讨论】:

      • 我没有单元测试(assertEquals)的经验,因此很难确定我应该从上述代码中提取哪些部分并将其集成到我的项目中
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-05-03
      • 1970-01-01
      • 1970-01-01
      • 2015-08-29
      • 1970-01-01
      • 2022-11-15
      • 1970-01-01
      相关资源
      最近更新 更多