-- android, java

Android :: JSON Parse İşlemleri – 1

Bu yazıda Android SDK kullanarak bir URL‘den JSON veri çekip parse etmekten bahsedelim. Burada kullanılacak yöntem veriyi manual parse etmek üzerinedir. URL’de bulunan JSON’ı String olarak alıp, sonrasında bu String’den bir JSONObject oluşturacağız. Son olarak da oluşturduğumuz bu JSONObject‘i parse edeceğiz.

json android

İçerik

  1. JSON Hakkında
  2. DefaultHttpClient Kullanarak URL’den JSON Çekme
  3. Çekilen String’i JSONObject’e Çevirme
  4. POJO Classlar
  5. JSONObject’in Parse Edilmesi
  6. Kodun Son Hali
  7. Kodun Logcat Çıktısı
  8. Referanslar
  9. Son Söz

JSON Hakkında


JSON (JavaScript Object Notation) hafif bir veri değişim formatıdır. İnsanların okuyup yazabilmesi kolaydır. Makinaların tarayıp, yaratabilmesi kolaydır. [via JSON’a Giriş [0]].
Wikipedia’daki örnek [1] üzerinden anlatacak olursak:

{
    "firstName": "John",
    "lastName": "Smith",
    "age": 25,
    "address": {
        "streetAddress": "21 2nd Street",
        "city": "New York",
        "state": "NY",
        "postalCode": 10021
    },
    "phoneNumber": [
        {
            "type": "home",
            "number": "212 555-1234"
        },
        {
            "type": "fax",
            "number": "646 555-4567"
        }
    ]
}

JSON içerisindeki { karakteri ile başlayan scope bir JSONObject [2] nesnesine, [ karakteri ile başlayan scope bir JSONArray [3] nesnesine karşılık gelmektedir. JSONArray, JSONObject dizisidir.

DefaultHttpClient Kullanarak URL’den JSON Çekme


Amazon’dan birkaç kitabın bilgileri ile oluşturduğum örnek JSON’ı şuraya[4] upload ettim. Buradaki JSON’ı alıp String olarak geri dönen bir metod ile işe başlayalım.

	private String getJsonFromUrl(String strUrl) {
		String strJson = null;
		InputStream is = null;
		try {
			DefaultHttpClient httpClient = new DefaultHttpClient();
			HttpPost httpPost = new HttpPost(strUrl);
			httpPost.setHeader("Content-type", "application/json");

			HttpResponse httpResponse = httpClient.execute(httpPost);
			HttpEntity httpEntity = httpResponse.getEntity();
			is = httpEntity.getContent();

			BufferedReader reader = new BufferedReader(new InputStreamReader(is, "utf-8"), 8);
			StringBuilder sb = new StringBuilder();
			String line = null;
			while ((line = reader.readLine()) != null) {
				sb.append(line + "\n");
			}
			is.close();
			strJson = sb.toString();
		} catch (Exception e) {
			e.printStackTrace();
			strJson = null;
		}
		return strJson;
	}

Bu metodun çalışabilmesi için AndroidManifest.xml dosyasına internete erişim iznini eklememiz gerekiyor:

<uses-permission android:name="android.permission.INTERNET" />

Çekilen String’i JSONObject’e Çevirme


Şimdi verilen URL’de bulunan JSON’ı aldığımıza göre onu parse edilebilir bir JSONObject’e çevirmemiz gerekiyor. Bunun için şu kodu kullanabiliriz:

	String strJson = getJsonFromUrl(URL);
	JSONObject jSonBooks = new JSONObject(strJson);

Tabi biraz zaman alabileceği için bu işlemleri bir AsyncTask [5] içinde yapmak mantıklı olacaktır.
Artık elimizde içinde bir kitap listesi tutan bir JSONObject var. Parse işlemine geçmeden önce bu kitapları [ve kitapların ISBN numaralarını] tutacak POJO[6] classlarımızı yazalım.

POJO Classlar


Kitapları temsil edeceğimiz Book classı:

public class Book {
	private Isbn isbn;
	private String name;
	private String author;
	private String language;
	private String publisher;
	private String coverImageUrl;
	private String paperback;
	private String price;

	public Book() {
		super();
	}

	public Book(Isbn isbn, String name, String author, String language, String publisher, String coverImageUrl,
			String paperback, String price) {
		super();
		this.isbn = isbn;
		this.name = name;
		this.author = author;
		this.language = language;
		this.publisher = publisher;
		this.coverImageUrl = coverImageUrl;
		this.paperback = paperback;
		this.price = price;
	}

	public Isbn getIsbn() {
		return isbn;
	}

	public void setIsbn(Isbn isbn) {
		this.isbn = isbn;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}

	public String getLanguage() {
		return language;
	}

	public void setLanguage(String language) {
		this.language = language;
	}

	public String getPublisher() {
		return publisher;
	}

	public void setPublisher(String publisher) {
		this.publisher = publisher;
	}

	public String getCoverImageUrl() {
		return coverImageUrl;
	}

	public void setCoverImageUrl(String coverImageUrl) {
		this.coverImageUrl = coverImageUrl;
	}

	public String getPaperback() {
		return paperback;
	}

	public void setPaperback(String paperback) {
		this.paperback = paperback;
	}

	public String getPrice() {
		return price;
	}

	public void setPrice(String price) {
		this.price = price;
	}

	@Override
	public String toString() {
		return "Book [isbn=" + isbn + ", name=" + name + ", author=" + author + ", language=" + language
				+ ", publisher=" + publisher + ", coverImageUrl=" + coverImageUrl + ", paperback=" + paperback
				+ ", price=" + price + "]\n";
	}
}

ve kitapların ISBN numaralarını temsil edecek olan Isbn classı:

public class Isbn {
	private String isbn10;
	private String isbn13;
	
	public Isbn() {
		super();
	}

	public Isbn(String isbn10, String isbn13) {
		super();
		this.isbn10 = isbn10;
		this.isbn13 = isbn13;
	}

	public String getIsbn10() {
		return isbn10;
	}

	public void setIsbn10(String isbn10) {
		this.isbn10 = isbn10;
	}

	public String getIsbn13() {
		return isbn13;
	}

	public void setIsbn13(String isbn13) {
		this.isbn13 = isbn13;
	}

	@Override
	public String toString() {
		return "Isbn [isbn10=" + isbn10 + ", isbn13=" + isbn13 + "]";
	}
}

Tasarımın eksikliğine takılmayalım, her şey örneği basit tutmak için :)

JSONObject’in Parse Edilmesi


Elimizde JSONObject ve Book ile Isbn classları hazır olduğuna göre artık parse işlemine geçebiliriz.
Çekilen String’i JSONObject’e Çevirme kısmının sonunda elde ettiğimiz JSONObject’i parametre olarak alan ve geriye Book türünde objeler tutan bir ArrayList döndüren bir metod yazalım:

	private List<Book> getBookListFromJson(JSONObject jSon) {
		String tagBooklist   = "booklist";
		String tagBook       = "book";
		String tagIsbn       = "isbn";
		String tagIsbn10     = "isbn-10";
		String tagIsbn13     = "isbn-13";
		String tagName       = "name";
		String tagAuthor     = "author";
		String tagLanguage   = "language";
		String tagPublisher  = "publisher";
		String tagCoverImage = "coverImage";
		String tagPaperback  = "paperback";
		String tagPrice      = "price";
		
		List<Book> list = new ArrayList<Book>();
		Book book = null;
		Isbn isbn = null;
		
		try {
			/** root -> booklist */
			JSONObject jSonRoot = jSon.getJSONObject(tagBooklist);
			
			/** array -> book */
			JSONArray jSonArrayBook = jSonRoot.getJSONArray(tagBook);
			
			/** book count */
			int length = jSonArrayBook.length();
			
			for (int i = 0; i < length; i++) {
				JSONObject jSonBook = (JSONObject) jSonArrayBook.get(i);
				JSONObject jSonIsbn =  jSonBook.getJSONObject(tagIsbn);
				
				String isbn10 = jSonIsbn.getString(tagIsbn10);
				String isbn13 = jSonIsbn.getString(tagIsbn13);
				
				isbn = new Isbn(isbn10, isbn13);
				
				String name = jSonBook.getString(tagName);
				String author = jSonBook.getString(tagAuthor);
				String language = jSonBook.getString(tagLanguage);
				String publisher = jSonBook.getString(tagPublisher);
				String coverImage = jSonBook.getString(tagCoverImage);
				String paperback = jSonBook.getString(tagPaperback);
				String price = jSonBook.getString(tagPrice);
				
				book = new Book(isbn, name, author, language, publisher, coverImage, paperback, price);
				list.add(book);
			}
		} catch (Exception e) {
			e.printStackTrace();
			list = null;
		}
		return list;
	}&#91;/java&#93;<h3>Metodlar</h3>
<div><strong>String'den JSONObject oluşturmak için:</strong>
[java]JSONObject jObject = new JSONObject(result);
JSONObject içerisinden belirli bir Stringi almak için:

String aJsonString = jObject.getString("STRING_NAME");
JSONObject içerisinden belirli bir Boolean’ı almak için:

Boolean aJsonBoolean = jObject.getBoolean("BOOLEAN_NAME");
JSONObject içerisinden belirli bir diziyi almak için:

JSONArray jArray = jObject.getJSONArray("ARRAY_NAME");
Dizinin elemanlarına ulaşmak için de:

for (int i=0; i < jArray.length(); i++)
{
    JSONObject oneObject = jArray.getJSONObject(i);
    String oneObjectsItem = oneObject.getString("STRINGNAMEinTHEarray");
    String oneObjectsItem2 = oneObject.getString("anotherSTRINGNAMEINtheARRAY");
}&#91;/java&#93;</div> [via How to parse JSON in Android [7]]
<a id="kodun-son-hali"><h2>Kodun Son Hali</h2></a>
Yukarıdaki işlemlerin tümünü içeren Activity kodu da aşağıdadır:
[java]import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONObject;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Window;

/**
 * 
 * @author Oguz
 * 
 */

public class Main extends Activity {
	private static final String URL = "https://oguzozkeroglu.com/download/android-java/booklist-json.txt";
	private JSONObject jSonBooks = null;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_main);
		
		new UrlTask().execute(URL);
	}

	private void init() {
		List<Book> listBook = getBookListFromJson(jSonBooks);
		
		for (Book book : listBook) {
			System.out.println("price -> " + book.getPrice() + " | book -> " + book.getName());
		}
	}

	private List<Book> getBookListFromJson(JSONObject jSon) {
		String tagBooklist   = "booklist";
		String tagBook       = "book";
		String tagIsbn       = "isbn";
		String tagIsbn10     = "isbn-10";
		String tagIsbn13     = "isbn-13";
		String tagName       = "name";
		String tagAuthor     = "author";
		String tagLanguage   = "language";
		String tagPublisher  = "publisher";
		String tagCoverImage = "coverImage";
		String tagPaperback  = "paperback";
		String tagPrice      = "price";
		
		List<Book> list = new ArrayList<Book>();
		Book book = null;
		Isbn isbn = null;
		
		try {
			/** root -> booklist */
			JSONObject jSonRoot = jSon.getJSONObject(tagBooklist);
			
			/** array -> book */
			JSONArray jSonArrayBook = jSonRoot.getJSONArray(tagBook);
			
			/** book count */
			int length = jSonArrayBook.length();
			
			for (int i = 0; i < length; i++) {
				JSONObject jSonBook = (JSONObject) jSonArrayBook.get(i);
				JSONObject jSonIsbn =  jSonBook.getJSONObject(tagIsbn);
				
				String isbn10 = jSonIsbn.getString(tagIsbn10);
				String isbn13 = jSonIsbn.getString(tagIsbn13);
				
				isbn = new Isbn(isbn10, isbn13);
				
				String name = jSonBook.getString(tagName);
				String author = jSonBook.getString(tagAuthor);
				String language = jSonBook.getString(tagLanguage);
				String publisher = jSonBook.getString(tagPublisher);
				String coverImage = jSonBook.getString(tagCoverImage);
				String paperback = jSonBook.getString(tagPaperback);
				String price = jSonBook.getString(tagPrice);
				
				book = new Book(isbn, name, author, language, publisher, coverImage, paperback, price);
				list.add(book);
			}
		} catch (Exception e) {
			e.printStackTrace();
			list = null;
		}
		return list;
	}

	private String getJsonFromUrl(String strUrl) {
		String strJson = null;
		InputStream is = null;
		try {
			DefaultHttpClient httpClient = new DefaultHttpClient();
			HttpPost httpPost = new HttpPost(strUrl);
			httpPost.setHeader("Content-type", "application/json");

			HttpResponse httpResponse = httpClient.execute(httpPost);
			HttpEntity httpEntity = httpResponse.getEntity();
			is = httpEntity.getContent();

			BufferedReader reader = new BufferedReader(new InputStreamReader(is, "utf-8"), 8);
			StringBuilder sb = new StringBuilder();
			String line = null;
			while ((line = reader.readLine()) != null) {
				sb.append(line + "\n");
			}
			is.close();
			strJson = sb.toString();
		} catch (Exception e) {
			e.printStackTrace();
			strJson = null;
		}
		return strJson;
	}
	
	class UrlTask extends AsyncTask<String, Void, Void> {
		String strJson = null;
		
		@Override
		protected Void doInBackground(String... url) {
			strJson = getJsonFromUrl(url[0]);
			return null;
		}
		
		@Override
		protected void onPostExecute(Void result) {
			super.onPostExecute(result);
			try {
				jSonBooks = new JSONObject(strJson);
				init();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}

Kodun Logcat Çıktısı


Kitabın kapak fotoğrafı ve diğer bilgilerinin de yer aldığı güzel bir liste yapsak gayet şukela olurdu ama amaç burda parse etmek olduğu için kitapların fiyatlarını ve isimlerini loga bastırmakla yetiniyoruz.
price -> $36.54 | book -> Growing Object-Oriented Software
price -> $33.42 | book -> Clean Code: A Handbook of Agile Software Craftsmanship
price -> $44.75 | book -> Refactoring: Improving the Design of Existing Code
price -> $24.90 | book -> The Art of Unit Testing: With Examples in .Net
price -> $24.49 | book -> Test Driven Development
price -> $42.88 | book -> Test-Driven Development: A Practical Guide: A Practical Guide

Referanslar


0 -> http://www.json.org/json-tr.html
1 -> http://en.wikipedia.org/wiki/JSON#Data_types.2C_syntax_and_example
2 -> http://developer.android.com/reference/org/json/JSONObject.html
3 -> http://developer.android.com/reference/org/json/JSONArray.html
4 -> https://oguzozkeroglu.com/download/android-java/booklist-json.txt
5 -> http://developer.android.com/reference/android/os/AsyncTask.html
6 -> http://en.wikipedia.org/wiki/Plain_Old_Java_Object
7 -> http://stackoverflow.com/a/9606629/637724

Son Söz


Her türlü yorum, eleştiri veya eksik/yalan/yanlış bilgi bildirimi için konuya yorum bırakmanız ya da mail atmanız beni memnun edecektir.

Yorum yazın

Bu site, istenmeyenleri azaltmak için Akismet kullanıyor. Yorum verilerinizin nasıl işlendiği hakkında daha fazla bilgi edinin.

19 Yorum

  1. Merhabalar Oğuz Bey,
    Öncelikle paylaşımınız İçin teşekkür ederim. Verileri almış olduğunuz url de txt uzantılı bir metin mevcut. Bunun yerine bu bilgileri web sitenizin veritabanından çekmek isteseydiniz nasıl bir yöntem izlerdiniz. Bitirme projemde böyle bir uygulamaya ihtiyacım var yardım etmeniz beni çok memnun eder.
    İyi çalışmalar

  2. @Burak
    Bunun için restful webservis yazmanız gerekecektir.
    Java, Php, .net, Python.. hangi platformda yazmak isterseniz bolca örnek mevcut piyasada.

    Java için Jersey var önerebileceğim. Jersey ->[https://jersey.java.net/]
    Tutorial için de: REST with Java (JAX-RS) using Jersey – Tutorial [http://www.vogella.com/articles/REST/article.html]
    Python için de stackoverflow’da şöyle bir post var: Recommendations of Python REST (web services) framework? -> [http://stackoverflow.com/questions/713847/recommendations-of-python-rest-web-services-framework]

  3. Oğuz merhaba abi :)
    bende müsadenle bir şey ekliyim.
    httpClient.execute(httpPost); bunun yerine eğer,
    httpClient.execute(httpPost, new BasicResponseHandler()) yazarsak, bu metotdan geriye string dönüyor. o zaman da inputstream ile okuyup yazmaya falan gerek kalmıyor. kod daha basitleşiyor. bence tabi :)
    saygılar.

  4. Merhaba..Yukarıdaki uygulama parçası tam olarak ne yapıyor?Ben de androidde bi uygulama yapmaya başladım.İnternetten kaikatür,fıkra benzeri şeyleri çekecem.Ama nasıl yapacam,ne kullanacam henüz bilmiyorum.Yardımcı olursanız sevinirim…

  5. @Nida
    JSON parse işini manuel olarak yapmaya yarıyor. Bahsettiğin uygulamayı yapabilmek için önce fıkra / karikatür veren bir restful servis bulman lazım. Sonra ordan dönen yanıtı yukarıdaki benzer bir şekilde (ya da farklı birkaç yöntem daha var) parse edip, kullanabilirsin.

  6. merhaba hocam,JSon da bulunan özel bilgileri peki nasıl gizleyeceğiz acaba o konuda ne önerirsiniz,JSon çıktısını dışardak erişilmesini engellemek veya JSON da bulunan email ve telefon gibi özel bilgileri gizli yapmak,bu konuda ne önerirsiniz ?

  7. ayrıca bir sorum daha olacak book object içindeki isbn arrayList e erişmek için mutlaka class tanımlamaları yapılması mı gerekiyor ayrıyeten ? ben bunu tam anlamadım.direk node lardan bilgilere ulaşamıyor muyuz ?

  8. Merhaba.Wallpaper programı yapıyorum ve resimleri internetten çekip gridviewde gösteriyor.Ben biraz daha abartıp jsonla resimlerin url link’lerinide internetten çektiricem..Aslında linkleri jsonla çekmeyi başardım ancak linkleri String[ ] haline getiremedim.Yani String kutusu yapmalıyım ve linkler arasına virgül veya herhangi bir sey koyup ayırıp gridview e göndericem.Sistemim bu şekilde işliyor.
    Linkleri çektiğimde log.cat de şu şekilde gözüküyor.Örneğin;
    http: //i.imgur.com/X1Olcw8.jpg
    http: //i.imgur.com/E73u0LH.jpg
    http: //i.imgur.com/zA0Bx7k.jpg
    http: //i.imgur.com/6KqgT3J.jpg
    http: //i.imgur.com/5G3b5Bj.jpg

    Benim istediğim;
    http: //i.imgur.com/X1Olcw8.jpg,http: //i.imgur.com/E73u0LH.jpg,http: //i.imgur.com/zA0Bx7k.jpg,http: //i.imgur.com/6KqgT3J.jpg,http: //i.imgur.com/5G3b5Bj.jpg,

    Bu şekilde…Aralarına ayıraç olarak virgül koyuyorum.Yardım ederseniz sevinirim çok uğraştım ama nafile.Bu arada HashMap olayını denedim ancak ortalık çok karışıyor.

  9. @Gökhan
    Gizleme konusu için server tarafında bir authentication yapısı kurulabilir. Servisi çağıran client bir kullanıcı adı ve parola ile giderse belki istediğiniz sağlanmış olabilir.

    ISBN için de illa ki bir class tanımlamaya tabi ki gerek yok. Nasıl isterseniz öyle kullanabilirsiniz. O kullanım bu örneğe özel, benim seçtiğim bir yöntemdi.

  10. @Melih
    for döngüsü içinde elde ettiğiniz her bir URL için, for dışında tanımlanan bir diziye ekleme yapabilirsiniz ya da StringBuilder kullanarak her bir URL için URL değerini ve sonuna ‘,’ ekleyerek istediğiniz String değerini elde edebilirsiniz.

  11. Bunu sonunda bahsettiğin gibi Liste şeklinde var mı örneği ulaşabileceğim.

  12. merhaba ben json ile internette yapılan bir veritabanına veri gönderip ve çekme işlemi yapmayı planlıyorum. json ile hem veri gönderme hemde veri çekme yapabilir miyim?

  13. @ugur: Evet tabi ki yapabilirsin. Dil ve platform bağımsız şekilde verileri taşımak için JSON ya da XML kullanılabilir. Başka seçenekler de var tabi ki, bunlardan birini kullanmak zorunda da değilsin.

  14. Merhaba,

    Kullanıcı sürekli internetde olmadığını varsayarak uygulama ilk açıldığında ilgili JSON telefona kaydedilip, interne kapalı olduğunda telefonda ki JSON dan verileri okuma gibi bir işlemi nasıl yapabiliriz?

    Teşekkür ederim.

  15. @Fatih:
    Bunun için local database ya da SharedPreferences kullanılabilir. Birden fazla nesne modellenecekse ve aralarında ilişkiler olacaksa, database bu konuda daha kullanışlı olacaktır. Android SDK içinde SqLite desteği doğrudan gelmektedir, yanına da herhangi bir ORM kullanılarak (ORMLite, GreenDAO, Orman.. gibi) bahsettiğiniz işlem kolayca yapılabilir.

  16. verilen linkler ( [1] , [2] vb.) calismiyor sanirim duzeltebilirsen yararli olur ayrica yazi icinde tesekkurler ellerine saglik.

  17. afedersiniz alttaki referanslar kismini gormemistim.

  18. Merhabalar Hocam, Anlatım Çok Güzel Olmuş.

    Anlatımınıza Göre Uygulamayı Yaptım. Çok Teşekkür Ederim. Fakat Takıldığım Bir Nokta Var.
    Kendi Yaptığım ROMA OTA Desteği veriyorum.
    Telefonun Versiyon Numarası 5.8.3 iken JSON Dosyasından Sürekli 5.8.18 VErsiyonunu İndiriyor. Normalde 5.8.23 Sürümünü İndirmesi Gerekiyor.

    Bunu nasıl çözebilirim. Yardımcı Olabilir misiniz ?

    JSON KOD:
    {
    “rom”:”Gionee Elife E3″,
    “url”:”http://www.miturkey.com/update_5.8.23.zip”,
    “md5″:”2247f306800c51cf2e3a74cb676e60b2”,
    “version”:”5.8.23″,
    “date”:”20150818-1232″,
    “changelog”:””
    },
    {
    “rom”:”Gionee Elife E3″,
    “url”:”http://www.miturkey.com/update_5.8.16.zip”,
    “md5″:”2247f306800c51cf2e3a74cb676e60b2”,
    “version”:”5.8.16″,
    “date”:”20150816-0823″,
    “changelog”:””
    }