【问题标题】:iterate through nested json object and save data in android sqlite遍历嵌套的json对象并将数据保存在android sqlite
【发布时间】:2014-03-07 15:10:57
【问题描述】:

我有一个嵌套的 JSON 对象,如下所示:

[
   {
  "question_id":"1",
  "description":"What is your gender ?",
  "widget_id":"1",
  "answers":[
     {
        "answer_text":"Male",
        "answer_id":"1"
     },
     {
        "answer_text":"Female",
        "answer_id":"2"
     }
  ]
   },
   {
  "question_id":"2",
  "description":"Which animal best describes your personality ?",
  "widget_id":"2",
  "answers":[
     {
        "answer_text":"Cat",
        "answer_id":"3"
     },
     {
        "answer_text":"Horse",
        "answer_id":"4"
     },
     {
        "answer_text":"Dove",
        "answer_id":"5"
     },
     {
        "answer_text":"Lion",
    "answer_id":"6"
    },
   {
            "answer_text":"Chameleon",
            "answer_id":"7"
     }
  ]
   },
   {
      "question_id":"3",
  "description":"Do you like meeting other people ?",
  "widget_id":"3",
  "answers":[

  ]
   },
   {
  "question_id":"4",
  "description":"On a scale of 1-10, how would you rate your sense of humour ?",
  "widget_id":"4",
  "answers":[

  ]
   },
   {
  "question_id":"5",
  "description":"Are you afraid of the dark ?",
  "widget_id":"1",
  "answers":[
     {
        "answer_text":"No",
        "answer_id":"8"
     },
     {
        "answer_text":"Yes",
        "answer_id":"9"
     }
  ]
   },
   {
  "question_id":"6",
  "description":"Is it true that cannibals do not eat clowns because they taste kind of funny ?",
  "widget_id":"3",
  "answers":[

  ]
   },
   {
  "question_id":"7",
  "description":"What is your email address ? (Optional)",
  "widget_id":"3",
  "answers":[

  ]
   }
]

从mysql服务器检索后,我试图插入sqlite android,如下所示,它可以工作。唯一的问题是我似乎失去了每个问题与其所有答案甚至widget_id之间的关系。因为一些问题有多个答案选项。

JSONArray aJson = new JSONArray(sJson);
ArrayList<Question> Question_Id_array = new ArrayList<Question>();

            for (int i = 0; i < aJson.length(); i++) {
                JSONObject json = aJson.getJSONObject(i);

                Question que = new Question();

                Question id = new Question();

                que.setDescription(json.getString("description"));

                id.setQuestionId(Integer.parseInt(json
                        .getString("question_id")));
                que.setWidgetId((Integer.parseInt(json
                        .getString("widget_id"))));
JSONArray cJson = json.getJSONArray("answers");
                ArrayList<Answer> ans = que.getAnswers();

                for (int k = 0; k < cJson.length(); k++) {
                    JSONObject Objectjson = cJson.getJSONObject(k);
                    Answer answer = new Answer();

                    answer.setAnswer_Text(Objectjson
                            .getString("answer_text"));
                    answer.setAnswer_Id(Integer.parseInt(Objectjson
                            .getString("answer_id")));
ans.add(answer);

String answer_value = answer.getAnswer_Text()
                            .toString();

                    int answer_id = answer.getAnswer_Id();

                    String question_title = que.getDescription().toString();

                    int question_id = que.getQuestionId();

                    int widget_id = que.getWidgetId();

                    ContentValues cv = new ContentValues();
                    cv.put(ResponseDetails.KEY_QUESTION_ID,question_id);
                    cv.put(ResponseDetails.KEY_QUESTION_DESCRIPTION,question_title);
                    cv.put(ResponseDetails.ANSWER_ID, answer_id);
                    cv.put(ResponseDetails.KEY_ANSWER_VALUE,answer_value);
                    cv.put(ResponseDetails.WIDGET_ID, widget_id);


                    getApplicationContext().getContentResolver()

                    .insert(ResponseContentProvider.CONTENT_URI2, cv);

                }

我目前有一个包含所有列的表,如代码中所示:

question_id、question_title、answer_id、answer_value 和 widget_id。

如何维护每个问题之间的 json 对象中存在的关系,所有问题的答案和小部件 ID 都同时 INSERTING 和 RETRIEVING 从 sqlite android。 p>

编辑

所以这是我现在得到的例外:

02-11 15:44:33.487: E/AndroidRuntime(1336): FATAL EXCEPTION: main
02-11 15:44:33.487: E/AndroidRuntime(1336): java.lang.NullPointerException
02-11 15:44:33.487: E/AndroidRuntime(1336):     at         com.mabongar.survey.TableAnswers.insert(TableAnswers.java:53)
02-11 15:44:33.487: E/AndroidRuntime(1336):     at     com.mabongar.survey.FragmentStatePagerActivity$FetchQuestions.onPostExecute(FragmentStatePagerActivity.java:    177)
02-11 15:44:33.487: E/AndroidRuntime(1336):     at    com.mabongar.survey.FragmentStatePagerActivity$FetchQuestions.onPostExecute(FragmentStatePagerActivity.java:    1)
02-11 15:44:33.487: E/AndroidRuntime(1336):     at android.os.AsyncTask.finish(AsyncTask.java:631)
02-11 15:44:33.487: E/AndroidRuntime(1336):     at     android.os.AsyncTask.access$600(AsyncTask.java:177)
02-11 15:44:33.487: E/AndroidRuntime(1336):     at   android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
02-11 15:44:33.487: E/AndroidRuntime(1336):     at   android.os.Handler.dispatchMessage(Handler.java:99)

还有一个

02-11 15:44:39.867: E/SQLiteLog(1357): (14) cannot open file at line 30191 of [00bb9c9ce4]
02-11 15:44:39.867: E/SQLiteLog(1357): (14) os_unix.c:30191: (2)   open(/data/data/com.mabongar.survey/databases/responsetable.db) - 
02-11 15:44:40.017: E/SQLiteDatabase(1357): Failed to open database    '/data/data/com.mabongar.survey/databases/responsetable.db'.
02-11 15:44:40.017: E/SQLiteDatabase(1357): android.database.sqlite.SQLiteCantOpenDatabaseException:   unknown error (code 14): Could not open database
02-11 15:44:40.017: E/SQLiteDatabase(1357):     at   android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)

编辑 *从 mysql 服务器下载的 FragmentStatePagerActivity,将值传递给 PagerAdapter,然后加载 Fragments*

public class FragmentStatePagerActivity extends ActionBarActivity {

public SQLiteDatabase db;
private final String DB_PATH = "/data/data/com.mabongar.survey/databases/";

private static final String DATABASE_NAME = "responsetable.db";
// AsyncTask Class

private class FetchQuestions extends AsyncTask<String, Void, String> {

    @SuppressWarnings("static-access")
    @Override
    protected String doInBackground(String... params) {

        if (params == null)

            return null;

        try{

            String mPath = DB_PATH + DATABASE_NAME;

            db = SQLiteDatabase.openDatabase(mPath, null, SQLiteDatabase.CONFLICT_NONE);

        }catch(SQLException e){

            Log.e("Error ", "while opening database");
            e.printStackTrace();
        }

//          // get url from params

        String url = params[0];

        try {
            // create http connection
            HttpClient client = new DefaultHttpClient();
            HttpGet httpget = new HttpGet(url);

            // connect
            HttpResponse response = client.execute(httpget);

            // get response
            HttpEntity entity = response.getEntity();

            if (entity == null) {
                return null;
            }

            // we get response content and convert it to json string
            InputStream is = entity.getContent();
            return streamToString(is);
        } catch (IOException e) {
            Log.e("Log message", "No network connection");
        }

        return null;
    }

}

如您所见,这就是我在 doInBackground() 方法中打开它的方式 然后我还在 pagerAdapter 类中打开它,因为它具有您刚刚在第二个答案中向我展示的 public ArrayList SelectAll() 方法。最后我在 TableAnswers 类和 TableQuestions 类中将其打开为好吧,因为我们正在向数据库中插入数据。

【问题讨论】:

    标签: android mysql json sqlite


    【解决方案1】:

    你必须创建两个表 1)问题父母 2)回答

    1)问题表字段:

        auto_Id (primary Key) auto increment
        question_id
        description
        widget_id
    

    2)答案表字段:

       auto_Id (primary Key) auto increment
       answer_text
       answer_id
       question_id
    
    public void table_question{
    //this functin is used for insert data .......when pass data from json
    public void insert(Arraylist<Model_question> modelArrlist){
    
         for (Model_question model : modelArrlist) {
        ContentValues values = new ContentValues();
            values.put(auto_Id, model.auto_Id);
            values.put(question_id, model.question_id);
            values.put(description, model.description);
            values.put(widget_id, model.widget_id);
            sqldb.insert(TableName, null, values);
    
            for(Model_answer model_answer :model.arrAnswerList)
            {
               model_answer.question_id=model.question_id
              Tbl_answer.insert(model_master);
            }
         }
    
    }
    }
    

    //这是tbl_answer插入方法

    public class tbl_answer{
    
    public void insert(Model_answer model_answer){
    
        ContentValues values = new ContentValues();
            values.put(auto_Id, model.auto_Id);
            values.put(question_id, model.question_id);
            values.put(answer_text, model.answer_text);
          values.put(answer_id, model.answer_id);
    
          }
    }
    
    
    public void Model_question {
    
        public String question_id,
            description,
            widget_id;
       public List<Model_answer> arrAnswerList=new ArrayList<Model_answer>;
    }
    
    public void Model_answer{
    
        public String answer_text,
           answer_id,
           question_id;
    
     }
    

    请检查此代码,此代码将有助于将数据插入到两个表中..成功..

    【讨论】:

    • 嗨@dipali 非常感谢您的解释。我正在立即对我的代码进行必要的更改以尝试一下。但是,我不明白最后两种方法table_answer 类。Model_question 和 Model_answer 方法什么都不做?
    • 这是独立的 java 类而不是方法
    • 哦,现在我明白了。因为我已经有了问题和答案对象,它使工作变得更容易了。我肯定会的。这是我经过几天的搜索后得到的最有用的答案!由于我现在知道如何插入,当我想从 sqlite 检索问题以显示在 textView 中时,我是否使用类似 - model.getQuestionDescription() 的东西?
    • 嗨@dipali。我还没有。我在从 sqlite 检索值时遇到了一些挑战。在你向我展示了如何保存它们之后。我正在从 mysql 下载测验server.then 在一个活动中传递然后将它们保存到 sqlite。我有一个 FragmentStatePagerAdapter 类,然后将每个问题传递到一个片段上。所以我被困在寻呼机适配器类以及如何从 sqlite db 中检索值。
    【解决方案2】:

    您可以根据 QuestionId 创建模型类的对象。您的模型类将包含一个 ArrayList of Answers,这将是另一个模型类。根据问题 ID,您有一个对象可以包含该问题的所有答案。

    这可以通过 for each 循环来确定。

    class QuestionModel {
      String questionId;
      String description;
      String widgetId;
      ArrayList<Answers> answers;
      //getter setters here
    }  
    
    class AnswersModel{
     String answerText;
     String answerId;
    //getter setter
    }  
    

    插入时,为每个循环使用一个 -> 为 QuestionModel 中的每个对象和答案列表 -> 匹配问题 ID 并相应地插入。
    检索时,您已整理好列表。
    http://docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html
    How does the Java 'for each' loop work?

    此外,您可以使用 Gson 并将响应直接映射到您的类,而不是像在您的代码中那样解析 json,例如:

    Gson gson = new Gson();
    QuestionModel questionModel= new QuestionModel();
    questionModel= gson.fromJson(responseContent,QuestionModel.class); 
    //where responseContent is your jsonString  
    

    那么您不必单独处理解析或检查 Answer 数组。
    检查:https://code.google.com/p/google-gson/

    对于命名差异(根据webservice中的变量),可以使用@SerializedName等注解。 (所以不需要使用Serializable)

    【讨论】:

    • 感谢 @user2450263 的建议。我正在研究 for each 循环,特别是因为很明显我需要在这里。我的代码中已经有了问题和答案对象。所以我我会执行你和 dipali 的建议,让你们知道它是如何工作的。
    【解决方案3】:
    public static ArrayList<Model_question> SelectAll() 
        ArrayList<Model_question> arrModelList = null;
            Cursor cursor = null;
            String Query = "Select * from " + TableName;
            cursor = sqldb.rawQuery(Query, null);
            if (cursor != null && cursor.moveToFirst()) {
                arrModelList = new ArrayList<Model_question>();
                do {
                    Model_question model = new Model_question();
                            model.auto_Id= (cursor.getString(cursor.getColumnIndex("auto_Id")));
    
                    model.question_id= (cursor.getString(cursor.getColumnIndex("question_id")));
                    model.description= (cursor.getString(cursor
                            .getColumnIndex("description")));
                    model.widget_id= (cursor.getString(cursor.getColumnIndex("widget_id")));
                            model.arrAnswerList= Tbl_answer
                            .selectIdWiseData(model.question_id);
                    arrModelList.add(model);
                } while (cursor.moveToNext());
                cursor.close();
            }// end if(cursor!=null)
            return arrModelList;
        }
    }
    
    public void selectIdWiseData(String question_id){
    
    ArrayList<Model_answer> arrayList = null;
            Log.d("tag", "Model_answerId" + inId);
            String Query = "Select * from " + TableName
                    + " where question_id='" + question_id+ "'";
            Log.d("tag", "Model_answer Query" + Query);
            Cursor cursor = sqldb.rawQuery(Query, null);
            if (cursor != null && cursor.moveToFirst()) {
                arrayList = new ArrayList<Model_answer>();
                do {
                    Model_answer model = new Model_answer();
                    model.autoId = (cursor.getString(cursor.getColumnIndex(AUOTID)));
                    model.question_id= (cursor.getString(cursor
                            .getColumnIndex("question_id")));
                    model.answer_text= (cursor.getString(cursor
                            .getColumnIndex("answer_text")));
    model.answer_id= (cursor.getString(cursor
                            .getColumnIndex("answer_id")));
    
    
                    arrayList.add(model);
                } while (cursor.moveToNext());
                cursor.close();
            }// end if(cursor!=null)
            return arrayList;
    }
    

    【讨论】:

    • @dipali.i 正在进行必要的更改,并会在几分钟后通知您。
    • 在对您上面显示的内容进行更改后,我不断收到我在编辑中添加的错误异常。
    • 好吧@dipali.tomorrow 还是可以的。非常感谢你和我一起浏览这段代码。非常有耐心! :-) 不过要澄清一下,我是说在你的第二个回答之后,我对如何检索数据进行了这些更改,但现在我得到一个“无法打开数据库错误异常”和“表答案类的空指针异常” .明天见:-)
    • @naffie你有没有打开sqldb?
    • @diplai 我有。在所有必要的地方。让我在我的代码中告诉你。我会添加另一个编辑。我会尽量坚持相关部分,因为它很长跨度>
    猜你喜欢
    • 2019-04-24
    • 1970-01-01
    • 2018-05-13
    • 1970-01-01
    • 1970-01-01
    • 2018-08-21
    • 1970-01-01
    相关资源
    最近更新 更多