نمایش محتویات json در listview

درس بعدی |||||‌ درس قبلی

JSON مخفف JavaScript Object Notation است. این یک قالب تبادل داده مستقل است و بهترین جایگزین برای XML است. در این درس نحوه تجزیه پرونده JSON و استخراج اطلاعات لازم از آن توضیح داده شده است.

اندروید چهار کلاس مختلف برای دستکاری داده های JSON فراهم می کند. این کلاسها JSONArray ، JSONObject ، JSONStringer و JSONTokenizer هستند.

اولین قدم ، شناسایی فیلدهای موجود در داده های JSON است که به آنها علاقه دارید. به عنوان مثال. در JSON که در زیر آورده شده است ما علاقه مندیم فقط دما را بدست آوریم.

{
   "sys":
   {
      "country":"GB",
      "sunrise":1381107633,
      "sunset":1381149604
   },
   "weather":[
      {
         "id":711,
         "main":"Smoke",
         "description":"smoke",
         "icon":"50n"
      }
   ],
	
  "main":
   {
      "temp":304.15,
      "pressure":1009,
   }
}

JSON – عناصر
یک پرونده JSON از اجزای بسیاری تشکیل شده است. در اینجا جدول تعریف اجزای یک فایل JSON و شرح آنها است –

1 Array ([): در یک پرونده JSON ، براکت مربع ([) یک آرایه JSON را نشان می دهد

2 شی ({): در یک فایل JSON ، آکولاد ({) نمایانگر یک شی JSON است

3 کلید: یک شی JSON شامل یک کلید است که فقط یک رشته است. جفت کلید / مقدار یک شی J JSON را تشکیل می دهد

4 Value: هر کلید دارای مقداری است که می تواند رشته ای ، صحیح یا غیره باشد.

تجزیه و تحلیل JSON
برای تجزیه و تحلیل یک شی JSON ، ما یک شی از کلاس JSONObject ایجاد می کنیم و یک رشته حاوی داده های JSON را برای آن مشخص می کنیم. نحو آن بصورت زیر است:

String in;
JSONObject reader = new JSONObject(in);

آخرین مرحله تجزیه JSON است. یک پرونده JSON از اشیای مختلفی با جفت کلید / مقدار متفاوت تشکیل شده است. بنابراین JSONObject عملکرد جداگانه ای برای تجزیه هر یک از مولفه های پرونده JSON دارد. نحو آن در زیر آورده شده است :

JSONObject sys  = reader.getJSONObject("sys");
country = sys.getString("country");
			
JSONObject main  = reader.getJSONObject("main");
temperature = main.getString("temp");

متد getJSONObject شی JSON را برمی گرداند. متد getString مقدار رشته کلید مشخص شده را برمی گرداند. جدا از این روشها ، روشهای دیگری نیز برای تجزیه بهتر فایلهای JSON توسط این کلاس ارائه شده است. این روش ها در زیر ذکر شده است:

1 get (نام رشته): این روش فقط مقدار را برمی گرداند اما به شکل نوع Object است

2 getBoolean (نام رشته) این روش مقدار بولی مشخص شده توسط کلید را برمی گرداند

3 getDouble (نام رشته) این روش مقدار دوگانه مشخص شده توسط کلید را برمی گرداند

4 getInt (نام رشته) این روش مقدار صحیح مشخص شده توسط کلید را برمی گرداند

5 getLong (نام رشته) این روش مقدار طولانی مشخص شده توسط کلید را برمی گرداند

6 length () این روش تعداد نگاشت های نام / مقدار را در این شی برمی گرداند.

7 names () این روش آرایه ای را شامل می کند که شامل نام رشته ها در این شی باشد.

مثال: برنامه ای بنویسید که فایل JSON که حاوی اطلاعات دانشجو است را مورد تجزیه و تحلیل قرار دهد و در یک لیست ویو نمایش دهد.

این فایل با پسوند json است که محتوای آن بصورت زیر است:

 [
      {
         "name": "ali",
         "lastname": "alavi",
         "phone": "1912"
      },
      {
         "name": "reza",
         "lastname": "razavi",
         "phone": "852125"
      },
      {
         "name": "hasan",
         "lastname": "hasani",
         "phone": "258008"
      },
      {
         "name": "hamid",
         "lastname": "hamedi",
         "phone": "2589631"
      },
      {
         "name": "neda",
         "lastname": "naderi",
         "phone": "214785"
      },
      {
         "name": "korosh",
         "lastname": "kordi",
         "phone": "258521"
      },
      {
         "name": "kazem",
         "lastname": "nbaloocji",
         "phone": "258745"
      }
   ]

در اندروید استودیو یک پوشه از نوع raw ایجاد می کنیم و فایل را در آن کپی می کنیم. پوشه raw بصورت زیر ساخته می شود:

ایجاد دایرکتوری raw

سپس باید کلاسی برای مدل کردن محتوای فایل JSON ایجاد کنیم. در نتیجه سه صفت name lastname و phone را ایجاد می کنیم. سپس متدهای سازنده و getter و setter آنرا میسازیم:

public class Contact {
    private String title;
    private String phone1;
    private String phone2;

    public Contact(String title, String phone1, String phone2) {
        this.title = title;
        this.phone1 = phone1;
        this.phone2 = phone2;
    }

    public Contact() {
    }

    public String getTitle() {
        return title;
    }

    public String getPhone1() {
        return phone1;
    }

    public String getPhone2() {
        return phone2;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setPhone1(String phone1) {
        this.phone1 = phone1;
    }

    public void setPhone2(String phone2) {
        this.phone2 = phone2;
    }

    public String toString(){
        return title+"    "+phone1+"\n"+"     "+phone2;
    }
}

متد toString برای نحوه نمایش در ابزار ListView است.

سپس یک کلاس دیگر ایجاد می کنیم با نام ContactJSONParser تا از طریق آن محتوای JSON را تجزیه و تحلیل کنیم. برای این منظور ابتدا یک متد با نام parseJSON‌ ایجاد می کنیم. خروجی این متد لیستی از آیتم هایی است که مطابق مدل کلاس Contact ایجاد شده اند:

public class ContactJSONParser {

    public List<Contact> parseJSON(String jsonString){
        List<Contact> contactList =new ArrayList<>();
        try {
            JSONArray jsonArray=new JSONArray(jsonString);
            for (int i=0;i<jsonArray.length();i++){

                JSONObject jsonObject=jsonArray.getJSONObject(i);
                Contact contact=new Contact();
                contact.setTitle(jsonObject.getString("name"));
                contact.setPhone1(jsonObject.getString("lastname"));
                contact.setPhone2(jsonObject.getString("phone"));
                contactList.add(contact);
                Log.i("json","OK");
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return contactList;
    }

همانطوریکه مشاهده می شود ورودی متد parseJSON یک رشته با نام jsonString است. این رشته همان محتوای فایل contact.json‌ است. از آنجاییکه محتوای فایل از نوع stream است آنرا به کمک متد convertInputStream2String به رشته تبدیل می کنیم. ورودی این تابع از نوع InputStream است و خروجی آن از نوع String است. کد آن در زیر آمده است:

 public String convertInputStream2String(InputStream inputStream) throws IOException {
        StringBuilder stringBuilder=new StringBuilder();
        BufferedInputStream bufferedInputStream=new BufferedInputStream(inputStream);
        while (bufferedInputStream.available()!=0){
            stringBuilder.append((char)bufferedInputStream.read());
        }
        bufferedInputStream.close();
        return stringBuilder.toString();
    }

برای ساخت رشته از کلاس StringBuilder استفاده می شود و محتوا هر دفعه در بافر (BufferInputStream) ذخیره می شود و تا زمانی که به انتهای فایل نرسیده به رشته stringBuilder اضافه می شود. رشته ساخته شده خروجی این متد است. محتوای کامل کلاس ContactJSONPaser در زیر آمده است:

public class ContactJSONParser {

    public List<Contact> parseJSON(String jsonString){
        List<Contact> contactList =new ArrayList<>();
        try {
            JSONArray jsonArray=new JSONArray(jsonString);
            for (int i=0;i<jsonArray.length();i++){

                JSONObject jsonObject=jsonArray.getJSONObject(i);
                Contact contact=new Contact();
                contact.setTitle(jsonObject.getString("name"));
                contact.setPhone1(jsonObject.getString("lastname"));
                contact.setPhone2(jsonObject.getString("phone"));
                contactList.add(contact);
                Log.i("json","OK");
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return contactList;
    }

    public String convertInputStream2String(InputStream inputStream) throws IOException {
        StringBuilder stringBuilder=new StringBuilder();
        BufferedInputStream bufferedInputStream=new BufferedInputStream(inputStream);
        while (bufferedInputStream.available()!=0){
            stringBuilder.append((char)bufferedInputStream.read());
        }
        bufferedInputStream.close();
        return stringBuilder.toString();
    }
}

حال به mainActivity.xml میرویم و یک ListView در آن قرار می دهیم. کد این فایل به صورت زیر آمده است:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/list"/>


</LinearLayout>

در ادامه به MainActivity.java میرویم و ابتدا محتوای فایل contact.json را می خوانیم:

 InputStream inputStream=getResources().openRawResource(R.raw.newjson);

سپس محتوا با فراخوانی متد convertStream2String به رشته تبدیل می شود. رشته برای متد parseJSON‌ ارسال می شود. با تجزیه تحلیل رشته ورودی در لیست قرار می گیرد این لیست contacts نام دارد و بصورت عمومی بصورت زیر تعریف می شود:

 private List<Contact> contacts;

کد مربوط به تبدیل محتوای فایل به لیست بصورت زیر آمده است:

ContactJSONParser contactJSONParser=new ContactJSONParser();
       
 String contentFile= contactJSONParser.convertInputStream2String(inputStream);
Toast.makeText(this, contentFile, Toast.LENGTH_SHORT).show();
contacts=contactJSONParser.parseJSON(contentFile);
Toast.makeText(this, "Number of contacts: "+contacts.size(), Toast.LENGTH_SHORT).show();

در ادامه باید محتوای لیست contacts را در لیست نمایش داد. برای این منظور یک متد جدید در MainActivity ایجاد می کنیم که نام آن dispaly است:

 public void Display(){
        adapter=new ArrayAdapter<Contact>(this,android.R.layout.simple_list_item_1,contacts);
        listView.setAdapter(adapter);
    }

متغیر adapter نیز به صورت عمومی از نوع ArrayAdapter بصورت زیر تعریف می شود:

 private ArrayAdapter<Contact> adapter;

کد کامل کلاس MainActivity بصورت زیر است:

public class MainActivity extends AppCompatActivity {

    private List<Contact> contacts;
    ListView listView;
    private ArrayAdapter<Contact> adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        listView=findViewById(R.id.list);
        InputStream inputStream=getResources().openRawResource(R.raw.newjson);
        ContactJSONParser contactJSONParser=new ContactJSONParser();
        try {
            String contentFile= contactJSONParser.convertInputStream2String(inputStream);
            Toast.makeText(this, contentFile, Toast.LENGTH_SHORT).show();
            contacts=contactJSONParser.parseJSON(contentFile);
            Toast.makeText(this, "Number of contacts: "+contacts.size(), Toast.LENGTH_SHORT).show();
            Display();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void Display(){
        adapter=new ArrayAdapter<Contact>(this,android.R.layout.simple_list_item_1,contacts);
        listView.setAdapter(adapter);
    }


}

با اجرای برنامه خروجی به صورت زیر نشان داده می شود: