جاوا و تکنولوژی های آن

java programming language

در این وبلاگ به بررسی نکات موجود در جاوا و تکنولوژی های آن می پردازیم

طبقه بندی موضوعی



سالها با Minimal-Json که حاصل تلاش Ralf Sternberg کار کردم یک کتابخانه ساده ، سریع و البته خوش کدی است که میتوانید ازش بسادگی استفاده کنید و حتی پیچیده ترین ساختار های Json را هم parse کنید و استفاده کنید


ولی وقتی بخواهید یک تناظر با Object داشته باشید و یکمی حرفه ای تر کار کنید نیاز داریم که کتابخانه های دیگری را استفاده کنیم

معمولا در کد هایی که زیاد از این Parser استفاده میشود مسئله پرفرمانس بسیار مهم خواهد بود و اصولا باید benchmark هایی را دید و اگر موجود نیست خودمان بین انتخاب هایمان بنچمارک کنیم 


مسئله اول Performance !! 

خوشبختانه بنچمارک بروزی در این ریپو قرار دارد که میتوان از روی آن انتخاب کرد 

https://github.com/fabienrenaud/java-json-benchmark





همانطور که میبینید dsl-json با اختلاف زیادی از کتابخانه های دیگری که در شرکت های بزرگی همچون گوگل دولوپ شده سریع تر است 


قبل از ادامه باید این نکته را ذکر کرد که کتابخانه ای که میخواهیم باید اول باید فیچر های کلیدی که ما حتما به آنها نیاز داریم را مشخص کنیم تا در وقت صرفه جویی شود 


فیچر هایی که من نیاز داشتم این گزینه ها بود :


موقع serialization : 

- فیلد هایی اجباری را مشخص کنم که مقدارش اگر null بود با خطا روبرو شوم

- فیلدهایی را بتوانم با مقدار null داشته باشم و در این حالت این فیلد ها ignore شوند 


موقع deserialization : 

- توانایی Object Mapping داشته باشد

- توانایی Simple Parser داشته باشد (گاهی پیش میاید که پیام دریافتی ممکن است چند حالت داشته باشد و از روی یک فیلدی میخواهید متوجه شوید که باید با کدامیک از Object های متناظر map شود )

- اگر فیلدی که نباید null باشد در پیام دریافتی json اگر غایب بود و یا null بود عملیات با خطا روبرو شود




خب حالا بریم سراغ کتابخانه ها 


dsl-json به آدرس : 

https://github.com/ngs-doo/dsl-json

این کتابخانه همه اون امکانات را با استفاده از settings تعریف شده دارد ولی simple parser را ندارد و همیشه باید از طریق Object متناظر مقادیر را دریافت کنیم 


jsoniter به آدرس :

 https://github.com/json-iterator/java

این کتابخانه همه موارد خواسته شده را با config تعریف شده دارد و simple parser هم قابل استفاده است 


jackson به آدرس :

https://github.com/FasterXML/jackson

https://github.com/FasterXML/jackson-databind

https://github.com/FasterXML/jackson-annotations


جکسون کتابخانه نسبتا سنگینی است ولی ویژگی های بسیار حرفه ای تری را دارا میباشد و برای موارد خیلی خاص بد نیست نگاهی به این کتابخانه اول بیاندازید و بدون تعریف کردن settings یا config خاصی و تنها با استفاده از annotation های مخصوص میتوان not null بودن و یا اجباری بودن فیلد برای داشتن مقدار را تعریف کنیم 



تست :

کتابخانه ها را از مخزن maven دریافت کنید 


کلاس POJO را تعریف میکنیم :


package test;

import com.dslplatform.json.CompiledJson;
import com.dslplatform.json.JsonAttribute;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.jsoniter.annotation.JsonIgnore;

@CompiledJson(onUnknown = CompiledJson.Behavior.IGNORE)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class POJO {

    @JsonAttribute(nullable = false, name = "number")
    @JsonProperty(required = true)
//    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    public Integer number;
//    @JsonAttribute(nullable = false, name = "name",mandatory = true)
//    @JsonInclude(JsonInclude.Include.NON_NULL)
//    @JsonProperty(required = true)
//    @com.jsoniter.annotation.JsonProperty(nullable = true,required = true)       
    public String name;
//    @JsonInclude(JsonInclude.Include.NON_NULL)
    public String detail;

    @Override
    public String toString() {
        return "POJO{" + "number=" + number + ", name=" + name + ", detail=" + detail + '}';
    }

}


کلاس تست :


package test;

import com.dslplatform.json.DslJson;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jsoniter.JsonIterator;
import com.jsoniter.any.Any;
import com.jsoniter.output.JsonStream;
import com.jsoniter.spi.Config;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.logging.Level;
import java.util.logging.Logger;

public class JsonTest {

    static String jsonStr1 = "{\"number\": 3,\"name\":\"سام\",\"detail\":\"detail for sam\"}";
    static String jsonStr2 = "{\"number\": 3,\"name\":null,\"detail\":\"detail for sam\"}";
    static String jsonStr3 = "{\"number\": 3,\"detail\":\"detail for sam\"}";

    public final static ObjectMapper jsonMapper;

    static {
        jsonMapper = new ObjectMapper();
    }

    public static void p(Object o) {
        if (o != null) {
            System.out.println(o.toString());
        }
    }

    public static void p(Object... o) {
        for (Object oo : o) {
            p(oo);
        }
    }

    public static void jacksonSerialize() {
        p("================== Jackson Serialize ==================");
        try {
            POJO po = new POJO();
            po.number = 1;
            po.name = "name1";
            po.detail = "detail1";

            String json1 = jsonMapper.writeValueAsString(po);
            p("json1:", json1);

            po.number = 2;
            po.name = null;
            po.detail = "detail1";

            String json2 = jsonMapper.writeValueAsString(po);
            p("json2:", json2);

        } catch (JsonProcessingException ex) {
            Logger.getLogger(JsonTest.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public static void jacksonDeserialize() {
        p("================== Jackson Deserialize ==================");
        try {
            JsonNode readTree1 = jsonMapper.readTree(jsonStr1);
            p("readTree 1:", readTree1.get("name"));
            JsonNode readTree2 = jsonMapper.readTree(jsonStr2);
            p("readTree 2:", readTree2.get("name"));
            JsonNode readTree3 = jsonMapper.readTree(jsonStr3);
            p("readTree 3:", readTree3.get("name"));

            POJO po1 = jsonMapper.readValue(jsonStr1, POJO.class);
            p("POJO 1:", po1);
            POJO po2 = jsonMapper.readValue(jsonStr2, POJO.class);
            p("POJO 2:", po2);
            POJO po3 = jsonMapper.readValue(jsonStr3, POJO.class);
            p("POJO 3:", po3);

        } catch (JsonProcessingException ex) {
            Logger.getLogger(JsonTest.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public static void jsoniterSerialize() {
        p("================== Jsoniter Serialize ==================");
        POJO po = new POJO();
        po.number = 1;
        po.name = "name1";
        po.detail = "detail1";
        Config config = new Config.Builder().omitDefaultValue(true).build();
        String json1 = JsonStream.serialize(config, po);
//        String json1 = JsonStream.serialize(po);
        p("json1:", json1);

        po.number = 2;
        po.name = null;
        po.detail = "detail1";

        String json2 = JsonStream.serialize(config, po);
        p("json2:", json2);

    }

    public static void jsoniterDeserialize() {
        p("================== Jsoniter Deserialize ==================");

        Any any1 = JsonIterator.deserialize(jsonStr1);
        p("any 1:", any1.get("name"));
        Any any2 = JsonIterator.deserialize(jsonStr2);
        p("any 2:", any2.get("name"));
        Any any3 = JsonIterator.deserialize(jsonStr3);
        p("any 3:", any3.get("name"));

        POJO po1 = JsonIterator.deserialize(jsonStr1, POJO.class);
        p("POJO 1:", po1);
        POJO po2 = JsonIterator.deserialize(jsonStr2, POJO.class);
        p("POJO 2:", po2);
        POJO po3 = JsonIterator.deserialize(jsonStr3, POJO.class);
        p("POJO 3:", po3);

    }

    public static void dslJsonSerialize() {
        try {
            p("================== DSL Json Serialize ==================");

            DslJson.Settings<Object> setting = new DslJson.Settings<>().includeServiceLoader();
            setting.skipDefaultValues(true);

            DslJson<Object> dsl = new DslJson<>(setting);

            POJO po = new POJO();
            po.number = 1;
            po.name = "name1";
            po.detail = "detail1";

            ByteArrayOutputStream os = new ByteArrayOutputStream();
            dsl.serialize(po, os);
            String json1 = os.toString("UTF-8");
            p("json 1: ", json1);

            po.number = 2;
            po.name = null;
            po.detail = "detail1";
            os = new ByteArrayOutputStream();
            dsl.serialize(po, os);
            String json2 = os.toString("UTF-8");
            p("json2:", json2);

        } catch (IOException ex) {
            Logger.getLogger(JsonTest.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    public static void dslJsonDeserialize() {
        try {
            p("================== DSL Json Deserialize ==================");

            DslJson.Settings<Object> setting = new DslJson.Settings<>().includeServiceLoader();
            setting.skipDefaultValues(true);
            DslJson<Object> dsl = new DslJson<>(setting);
            /*
             missing simple json parser
             */
            byte[] bytes = jsonStr1.getBytes(StandardCharsets.UTF_8);
            POJO po1 = dsl.deserialize(POJO.class, bytes, bytes.length);
            p("POJO 1:", po1);
            bytes = jsonStr2.getBytes(StandardCharsets.UTF_8);
            POJO po2 = dsl.deserialize(POJO.class, bytes, bytes.length);
            p("POJO 2:", po2);
            bytes = jsonStr3.getBytes(StandardCharsets.UTF_8);
            POJO po3 = dsl.deserialize(POJO.class, bytes, bytes.length);
            p("POJO 3:", po3);
        } catch (IOException ex) {
            Logger.getLogger(JsonTest.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    public static void main(String[] args) {
        jacksonSerialize();
        jsoniterSerialize();
        dslJsonSerialize();
        jacksonDeserialize();
        jsoniterDeserialize();
        dslJsonDeserialize();
    }

}



با توجه به ویژگی های کلیدی که داشتم و سرعت بیشتر و حجم کمتر اشغال رم کتابخانه jsoniter میتواند انتخاب خوبی باشد البته باید در نظر بگیریم که تعداد دلوپر و آپدیت های این کتابخانه قابل مقایسه با Jackson نیست









نظرات  (۰)

هیچ نظری هنوز ثبت نشده است

ارسال نظر

ارسال نظر آزاد است، اما اگر قبلا در بیان ثبت نام کرده اید می توانید ابتدا وارد شوید.
شما میتوانید از این تگهای html استفاده کنید:
<b> یا <strong>، <em> یا <i>، <u>، <strike> یا <s>، <sup>، <sub>، <blockquote>، <code>، <pre>، <hr>، <br>، <p>، <a href="" title="">، <span style="">، <div align="">
تجدید کد امنیتی