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.
İçerik
- JSON Hakkında
- DefaultHttpClient Kullanarak URL’den JSON Çekme
- Çekilen String’i JSONObject’e Çevirme
- POJO Classlar
- JSONObject’in Parse Edilmesi
- Kodun Son Hali
- Kodun Logcat Çıktısı
- Referanslar
- 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; }[/java]<h3>Metodlar</h3> <div><strong>String'den JSONObject oluşturmak için:</strong> [java]JSONObject jObject = new JSONObject(result);
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
@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]
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.
Teşekkürler Resul.
Ben de bilmiyordum iyi olmuş yazdığın. Yazının altında bulunsun :)
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…
@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.
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 ?
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 ?
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.
@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.
@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.
Bunu sonunda bahsettiğin gibi Liste şeklinde var mı örneği ulaşabileceğim.
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?
@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.
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.
@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.
verilen linkler ( [1] , [2] vb.) calismiyor sanirim duzeltebilirsen yararli olur ayrica yazi icinde tesekkurler ellerine saglik.
afedersiniz alttaki referanslar kismini gormemistim.
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”:””
}