Saturday, August 28, 2010

JACKSON ile JSON işleme

Jackson, JSON ayrıştıran, üreten, işleyen bir Java Kütüphanesidir.
Peki nedir bu JSON?

Açılımı JavaScript Object Notation. Nesne gösterme formatı. İnsanın daha kolay okuyabileceği veri tanımla biçimidir. JSON programlama dili değildir. XML ile alternatif olarak gösterilebilir. http://www.json.org/xml.html adresinde XML ile karşılaştırmasını görebilirsiniz.


JSON formatındaki bir veride, nesneler, diziler, katar, sayı değerler olabilir. Aşağıda bir JSON örneği mevcuttur.

{hayvanlar:{
kedi:[
{
isim:"ciguli",
renk:"beyaz",
cins:"iran"
},
{
isim:"binnaz",
renk:"lacivert",
cins:"van"
}
],
sayi:125
}

JSON'da Nesne kavramı isim-değer ikilisini içeren yapı için verilen addır. Kıvırcık parantezler ({}) arasında kalan veridir. Yani örnekteki isim:"", renk:"", cins:"" (A nesnesi diyelim buna) ya da kedi:[...] gibi (buna da B nesnesi diyelim). B nesnesi, elemanları A nesnesi olan bir diziyi içerir. Diziler de köşeli parantezler ([]) arasında kalan veridir.

Json olarak üreteceğimiz ve eşleyeceğimiz sınıf olarak aşağıdaki yapı verilmiştir. Hayvanlar sınıfı, kedi listesinden ve sayidan oluşmaktadır.

Hayvanlar.Java
import java.util.ArrayList;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonProperty;

public class Hayvanlar {
@JsonProperty("kedi")
private ArrayList kediList;
private Integer sayi;

public Integer getSayi() {return sayi;}
public void setSayi(Integer sayi) {this.sayi = sayi;}

@JsonIgnore
public ArrayList getKediList() {return kediList;}
public void setKediList(ArrayList kediList) {this.kediList = kediList;}
}


Kedi.Java
public class Kedi {
private String isim;
private String renk;
private String cins;
public String getIsim() {return isim;}
public void setIsim(String isim) {this.isim = isim;}
public String getRenk() {return renk;}
public void setRenk(String renk) {this.renk = renk;}
public String getCins() {return cins;}
public void setCins(String cins) {this.cins = cins;}

}

Jackson ile JSON işlemenin 3 temel yolu vardır:



1) Düz Okuma (Streaming API




Yazması en basit, işleme süresi en hızlı olan yöntem budur. Yapıdaki her girdiyi tek tek tanımlayarak oluşturur ya da okursunuz.


JSON yapısına uygun veri oluşturmak için org.codehaus.jakson.JsonGenerator sınıfı, veir okuyup işlemek



içinse org.codehaus.jakson.JsonParser sınıfı kullanılır. Kolay bir method olmasına rağmen, yazılan kod uzun yapılan



iş diğer 2 yönteme göre daha fazladır.




JsonYaz.Java

Json yapısındaki veride her nesne, karakter tek tek yazılır.





JsonFactory jsonFactory = new JsonFactory(); // Temel Jackson sınıfı, JSON işleyicileri içerir
JsonGenerator jg = jsonFactory.createJsonGenerator(new File("GeneratedJson.txt"), JsonEncoding.UTF8); //Json üreten sınıf
jg.writeStartObject(); // Nesneyi başlatır. '{' karakteri koyar.
jg.writeFieldName("hayvanlar");
jg.writeStartObject();
jg.writeFieldName("kedi");
jg.writeStartArray(); // Diziyi başlatır. '[' karakteri koyar.
jg.writeStartObject();
jg.writeStringField("isim", "ciguli");
jg.writeStringField("renk", "beyaz");
jg.writeStringField("cins", "iran");
jg.writeEndObject();
jg.writeStartObject();
jg.writeStringField("isim", "binnaz");
jg.writeStringField("renk", "lacivert");
jg.writeStringField("cins", "van");
jg.writeEndObject();
jg.writeEndArray(); // Diziyi sonlandırır. ']' karakteri koyar
jg.writeNumberField("sayi", 125);
jg.writeEndObject(); // Nesneyi sonlandırır. '}' karakteri koyar.
jg.close();


JsonIsle.Java




JsonFactory jsonFactory = new JsonFactory();
JsonParser jp = jsonFactory.createJsonParser(new File("GeneratedJson.txt"));
JsonToken currentToken;
currentToken = jp.nextToken();

if(currentToken != JsonToken.START_OBJECT){
System.out.println("Yanlış format. Verilen dosyadaki JSON, { karakteri ile başlamalı");
return;
}

String fieldname;

while (jp.nextToken() != JsonToken.END_OBJECT) {
fieldname = jp.getCurrentName();
jp.nextToken();
if(fieldname.equals("hayvanlar")){
Hayvanlar hayvanlar = new Hayvanlar();
jp.nextToken();
fieldname = jp.getCurrentName();
if(fieldname.equals("kedi")){
List kediList = new ArrayList();
while(jp.nextToken() != JsonToken.END_ARRAY){
Kedi kedi = new Kedi();
while(jp.nextToken() != JsonToken.END_OBJECT){
String val = jp.getCurrentName();
if("isim".equals(val)){
kedi.setIsim(jp.getText());
}
else if("cins".equals(val)){
kedi.setCins(jp.getText());
}
else if("renk".equals(val)){
kedi.setCins(jp.getText());
}
}
kediList.add(kedi);
}
hayvanlar.setKediList(kediList);
}
else if(fieldname.equals("sayi")){
hayvanlar.setSayi(jp.getIntValue());
}
}
else{
return;
}
}

2) Eşleme (Mapping)




JSON dan okunacak verinin, ya da JSON oluşturacak verinin, Java Nesneleri yada POJO(sadece getter ve setteri olan Java nesnleri) ile eşleştirmesiyle yapılır. org.codehaus.jackson.map.ObjectMapper sınıfı kullanılarak nesne ile JSON birbirine bağlanır.


JsonOlusturMap.Java

Nesne yaratılır, değerleri atanır. Json oluştururken ObjectMapper ile nesne eşlenir. writeValue fonksiyonu ile nesnenin JSONu oluşturulur




Kedi kedi1 = new Kedi();
Kedi kedi2 = new Kedi();
kedi1.setIsim("isim1");
kedi1.setRenk("renk1");
kedi1.setCins("cins1");

kedi2.setIsim("isim2");
kedi2.setRenk("renk2");
kedi2.setCins("cins2");

Hayvanlar hayvanlar = new Hayvanlar();
ArrayList kediList = new ArrayList();
kediList.add(kedi1);
kediList.add(kedi2);

hayvanlar.setKediList(kediList);
hayvanlar.setSayi(250);

ObjectMapper objectMapper = new ObjectMapper();
System.out.println(objectMapper.writeValueAsString(hayvanlar));

// Hayvanlar etiketi ve nesnesini yazdırmak için map nesnesi oluşturulmuştur
HashMap hashMap = new HashMap();
hashMap.put("hayvanlar", hayvanlar);
System.out.println(objectMapper.writeValueAsString(hashMap));

Sonuc:



{"kedi":[{"isim":"isim1","renk":"renk1","cins":"cins1"},{"isim":"isim2","renk":"renk2","cins":"cins2"}],"sayi":250}
{"hayvanlar":{"kedi":[{"isim":"isim1","renk":"renk1","cins":"cins1"},{"isim":"isim2","renk":"renk2","cins":"cins2"}],"sayi":250}}


JsonIsleMap.Java

Yukarıda oluşturulan ilk sonuçtaki JSON MapRead.txt dosyasına atılır. Buradaki yapı hayvanlar sınıfının yapısında olduğu için objectMapper bu nesne ile eşlenir. Hayvanlar sınıfında "hayvanlar" diğer bir özellik olmadığı için hashmap kullanılmamıştır.




Hayvanlar hayvanlar2 = objectMapper.readValue(new File("MapRead.txt"), Hayvanlar.class);





3) Ağaç Modeli (Tree Model)

Bu modelde verilen JSON ağaç yapısı şşeklinde tutulur. Örneğimizdeki hayvanlar nesnesi kökteki düğüm, altında kedi ve sayi nesnelerini içerir. Kedi düğümü de altında dizin olan başka bir düğümdür. JsonNode sınıfını kullanır, alt ağaçlara ve buradan verilen etiketlerin değerlerine ulaşılabilir.




//JSON Ağaç Oku
ObjectMapper objectMapper = new ObjectMapper();
JsonFactory jf = new JsonFactory();
JsonParser jp = jf.createJsonParser(new File("GeneratedJson.txt"));
JsonNode jsonDugum = objectMapper.readTree(jp); // ağaç yapısı olarak okunup, en kökteki ağaç Json Düğümüne atanmış
JsonNode hayvanDugum = jsonDugum.path("hayvanlar"); //okunan Json verisinde hayvanlar düğümünün altı başka bir düğüme atanmış
String hayvanKatar = objectMapper.writeValueAsString(hayvanDugum); //deger okuma
System.out.println(hayvanKatar);

Kedi kedi1 = new Kedi();
Kedi kedi2 = new Kedi();

kedi1.setIsim("isim1");
kedi1.setRenk("renk1");
kedi1.setCins("cins1");

kedi2.setIsim("isim2");
kedi2.setRenk("renk2");
kedi2.setCins("cins2");

Hayvanlar hayvanlar = new Hayvanlar();
ArrayList kediList = new ArrayList();
kediList.add(kedi1);
kediList.add(kedi2);

hayvanlar.setKediList(kediList);
hayvanlar.setSayi(250);
// If you want to add "hayvanlar" tag and this object
HashMap hashMap = new HashMap();
hashMap.put("hayvanlar", hayvanlar);

//JSON Ağaç Yaz
JsonNode js = objectMapper.convertValue(hashMap, JsonNode.class);
JsonGenerator jg = jf.createJsonGenerator(new File("OutPutJson.txt"), JsonEncoding.UTF8);
objectMapper.writeTree(jg, js);


Sonuç olarak Jackson performansı iyi, çok fazla sınıf bulunduran bir json işlemek için güzel bir java kütüphanesidir. Performans değerlerini diğer kütüphanelerle karşılaştırmalı olarak bu linkten bakabilirsiniz.
Herkese iyi çalışmalar...






No comments: