أعتقد أن الجميع يعرف ما هو JSON. إذا كنت لا تعرف ، فهذا أمر خارج. جوجل. لن أقدم أي شيء هنا.
أعتقد أن الجميع نادراً ما يسمع عن Protobuffer ، ولكن إذا تم ذلك بواسطة Google ، أعتقد أن الجميع سيكونون مهتمين بتجربته. بعد كل شيء ، تكون صادرات Google في الغالب منتجات عالية الجودة.
Protobuffer هو بروتوكول نقل يشبه JSON. في الواقع ، لا يمكن قول أنه بروتوكول ، فهو مجرد شيء نقل البيانات.
إذن ما هو الفرق بينه وبين JSON؟
بين اللغة ، هذا هو واحد من مزاياه. يأتي مع برنامج التحويل البرمجي ، Protoc ، والذي يحتاج فقط إلى تجميعه ، ويمكن تجميعه في كود Java و Python و C ++. لا يوجد سوى هذه الثلاثة في الوقت الحالي ، لذلك لا تفكر في الآخرين في الوقت الحالي ، وبعد ذلك يمكنك استخدامها مباشرة دون كتابة أي رمز آخر. حتى تلك المحلية تأتي بالفعل معهم. JSON بالطبع هي لغة متعددة ، ولكن هذه اللغة المتقاطعة تعتمد على رمز الكتابة.
إذا كنت تريد معرفة المزيد ، يمكنك التحقق من ذلك:
https://developers.google.com/protocol-buffers/docs/overview
حسنًا ، دون مزيد من اللغط ، دعنا نلقي نظرة على سبب حاجة إلى مقارنة Protobuffer (المشار إليها فيما يلي باسم GPB) و JSON.
1. لأن JSON لديها تنسيق معين ويوجد في الشخصيات ، لا يزال هناك مجال للضغط في كمية البيانات. عندما تكون كمية البيانات الكبيرة على GPB أصغر بكثير من كمية JSON ، يمكننا أن نرى المثال أدناه.
2. إن الفرق الكفاءة بين مكتبات JSON كبيرة جدًا ، وهناك فجوة تبلغ حوالي 5-10 بين مكتبات Jackson و GSON (تم اختبار هذا مرة واحدة فقط ، إذا كان هناك أي خطأ ، فيرجى preat ذلك). يحتاج GPB فقط إلى واحدة ، ولا يوجد فرق بين ما يسمى بالعديد من المكتبات. بالطبع ، هذه النقطة تتكون فقط للأرقام ، ويمكن تجاهلها.
الحديث رخيص ، فقط أرني الرمز.
في عالم البرمجة ، يكون الكود دائمًا هو الملك ، لذلك دعنا نذهب إلى الكود.
قبل تحميل الرمز ، تحتاج إلى تنزيل protobuffer أولاً ، هنا:
https://github.com/google/protobuf
1. أولاً وقبل كل شيء ، يحتاج GPB إلى وجود ملف له تعريفات فئة مماثلة ، تسمى ملف proto.
دعنا نأخذ مثال الطلاب والمعلمين لتقديم مثال:
لدينا الملفان التاليان: student.proto
خيار java_package = "com.shun" ؛ خيار java_outer_classname = "studentproto" ؛ رسالة طالب {مطلوب int32 id = 1 ؛ اسم السلسلة الاختياري = 2 ؛ اختياري int32 العمر = 3 ؛ } </span> المعلم
استيراد "student.proto" ؛ خيار java_package = "com.shun" ؛ خيار java_outer_classname = "TeacherProto" ؛ المعلم رسالة {مطلوب int32 id = 1 ؛ اسم السلسلة الاختياري = 2 ؛ تكرار الطالب student_list = 3 ؛ } </span> هنا واجهنا بعض الأشياء الغريبة:
استيراد ، int32 ، المتكرر ، المطلوب ، اختياري ، خيار ، إلخ.
1) الاستيراد يعني استيراد ملفات proto الأخرى
2) يشير المطلوب والاختياري إلى ما إذا كان الحقل اختياريًا. هذا يحدد المعالجة التي سيتم إجراؤها بواسطة ProtoBuffer إذا كان للحقل قيمة أم لا. إذا لزم الأمر ، ولكن عند المعالجة ، لا يمر الحقل بالقيمة ، فسيتم الإبلاغ عن خطأ ؛ إذا تم وضع علامة اختيارية ، فلن يتم إرسال أي قيمة ، فلن تكون هناك مشكلة.
3) أعتقد أنه يمكنك فهم التكرار ، مما يعني ما إذا كانت متكررة ، فهي تشبه القائمة في Java.
4) الرسالة تعادل الفصل
5) يمثل الخيار الخيار ، حيث يمثل Java_Package اسم الحزمة ، أي اسم الحزمة المستخدمة عند إنشاء رمز Java. java_outer_classname هو اسم الفصل. لاحظ أن اسم الفئة هذا لا يمكن أن يكون هو نفس اسم الفصل في الرسالة أدناه.
بالنسبة للخيارات الأخرى والأنواع ذات الصلة ، يرجى زيارة الوثائق الرسمية.
2. مع هذه الوثائق ، ماذا يمكننا أن نفعل؟
تذكر المترجم الذي تم تنزيله أعلاه. قم بفك ضغطه ونحصل على protoc.exe. بالطبع ، يعتمد هذا على Windows. لم أفعل أنظمة أخرى. إذا كنت مهتمًا ، فيمكنك تجربتها.
أضف إلى المسار (من السهل إضافته أو لا ، إنه غير مريح) ، وبعد ذلك يمكنك إنشاء ملف الفصل الذي نحتاجه من خلال الملف أعلاه.
protoc -java_out = مسار لتخزين رمز المصدر -proto_path = مسار إلى ملف proto proto proto
-proto_path يحدد مسار المجلد لملف proto ، وليس ملفًا واحدًا ، ويستخدم بشكل أساسي للبحث عن ملفات الاستيراد ، ويمكن حذفه
إذا كنت بحاجة إلى وضع الرمز المصدر في d:/protobuffsjson/src ، يتم تخزين ملف proto الخاص بي في d:/protofiles
ثم أمر التجميع الخاص بي هو:
protoc -java_out = d:/protobuffsjson/src d: /protofiles/teacher.proto d: /protofiles/student.proto
لاحظ أنه في الملف الأخير هنا ، نحتاج إلى تحديد جميع الملفات التي تحتاج إلى تجميع.
بعد التجميع ، يمكنك رؤية الملف الذي تم إنشاؤه.
لم يتم نشر الرمز ، أكثر من اللازم. يمكنك إلقاء نظرة خاصة. هناك الكثير من البنائين في الكود. أعتقد أنك ستعرف أنه وضع البناء في لمحة.
في هذا الوقت ، يمكنك لصق الكود في مشروعك ، وبالطبع ، هناك الكثير من الأخطاء.
تذكر رمز المصدر الذي قمنا بتنزيله مسبقًا؟ قم بفك ضغطه ، لا تكن بلا رحمة. ثم ابحث عن SRC/Main/Java/لنسخ أحدها إلى مشروعك. بالطبع ، يمكنك أيضًا تجميع ANT أو Maven ، لكنني لست على دراية بهذين الأمرين ، لذلك لن أكون قبيحًا بعد الآن. ما زلت معتادًا على نسخها مباشرة إلى المشروع.
خطأ الكود ، هاها ، عادي. لسبب ما ، تصر Google على ترك مثل هذه الحفرة بالنسبة لنا.
عد إلى /java في دليل protobuffer وشاهد readme.txt ، وابحث عن جملة:
بعد النظر إليه ، أشعر أن هذا الرمز سيكون غريبًا بعض الشيء ، كما لو كان خطأ. على أي حال ، لم أقم بتنفيذه ، وأمرتي هي:
<span style = "font-size: 16px ؛"> protoc-java_out = أو مسار ملف proto حيث يتم وضع الرمز (هنا هو مسار ملف الواصف.
بعد التنفيذ ، يمكننا أن نرى أنه لا توجد أخطاء في الكود.
3. الخطوة التالية هي بالطبع اختبار.
دعونا نجري اختبار GPB كتابة أولاً:
حزمة com.shun.test ؛ استيراد java.io.fileOutputStream ؛ استيراد java.io.ioException ؛ استيراد java.util.arraylist ؛ استيراد java.util.list ؛ استيراد com.shun.studentProto.student ؛ استيراد com.shun.teacherproto.teacher ؛ PROMER CLASS PROTOWRITETEST {public static void main (string [] args) يلقي ioException {student.builder levuilder = student.newbuilder () ؛ الحفل. الحفل. levuilder.setName ("Shun") ؛ // قائمة قائمة القائمة <Tudture> StercuilderList = جديد ArrayList <Tudent> () ؛ Stervuilderlist.add (levuilder.build ()) ؛ المعلم. Teabuilder.setid (1) ؛ teabuilder.setName ("testtea") ؛ teabuilder.addallstudentList (stervuilderlist) ؛ // اكتب gpb إلى fileOutputStream fos = new FileOutputStream ("c: //users//shun//desktop//test/test.protoout") ؛ Teabuilder.build (). Writeto (FOS) ؛ fos.close () ؛ }} </span> دعونا نلقي نظرة على الملف ، إذا لم يحدث شيء غير متوقع ، فيجب إنشاءه.
بعد إنشاءه ، يجب أن نقرأه مرة أخرى.
حزمة com.shun.test ؛ استيراد java.io.fileInputStream ؛ استيراد java.io.filenotfoundException ؛ استيراد java.io.ioException ؛ استيراد com.shun.studentProto.student ؛ استيراد com.shun.teacherproto.teacher ؛ protoreadtest public {public static void main (string [] args) يلقي FileNotfoundException ، ioException {teacher Teacher.Parsefrom (new FileInputStream ("c: //users//shun//desktop//test/test/test.protoout")) ؛ System.out.println ("معرف المعلم:" + teacher.getId () + "، الاسم:" + teacher.getName ()) ؛ لـ (Study Stu: teacher.getStudentList ()) {system.out.println ("معرف الطالب:" + stu.getid () + "، الاسم:" + stu.getName () + "، العمر:" + stu.getage ()) ؛ }}}} </span> الكود بسيط للغاية لأن جميع التعليمات البرمجية التي تم إنشاؤها بواسطة GPB تتم بالنسبة لنا.
ما سبق يعرف الاستخدام الأساسي. سوف نركز على الفرق بين أحجام الملفات التي تم إنشاؤها في GPB و JSON. لن أنشر رمز JSON المفصل هنا. سأقوم بنشر مثال لاحقًا. إذا كنت مهتمًا ، فيمكنك تنزيله.
هنا نستخدم GSON لتحليل JSON. فيما يلي فقط رمز تحويل الكائن إلى JSON وكتابة الملف:
لن أكتب التعريفات الأساسية لطالب الفصول الدراسية والمعلم ، فقط افعلها كما تريد ، الرمز هو كما يلي:
حزمة com.shun.test ؛ استيراد java.io.filewriter ؛ استيراد java.io.ioException ؛ استيراد java.util.arraylist ؛ استيراد java.util.list ؛ استيراد com.google.gson.gson ؛ استيراد com.shun.student ؛ استيراد com.shun.teacher ؛ الطبقة العامة gsonwritetest {public static void main (string [] args) يلقي ioException {student stu = new student () ؛ Stu.Setage (25) ؛ Stu.SetID (22) ؛ Stu.SetName ("Shun") ؛ قائمة <Tudent> Stulist = new ArrayList <Tudent> () ؛ Stulist.add (Stu) ؛ المعلم المعلم = معلم جديد () ؛ المعلم. Teacher.setName ("Shun") ؛ المعلم. النتيجة السلسلة = GSON () filewriter fw = new filewRiter ("c: // user // shun/desktop // test // json") ؛ fw.write (نتيجة) ؛ fw.close () ؛ }} </span> بعد ذلك ، ندخل رسميًا رمز الاختبار الحقيقي. في البداية ، نضع كائنًا في القائمة. بعد ذلك ، نختبر أحجام الملفات التي تم إنشاؤها بواسطة GPB و JSON بدورها.
تحسين رمز GPB السابق ، دعه ينشئ عدد مختلف من القوائم وتجديد الملفات:
حزمة com.shun.test ؛ استيراد java.io.fileOutputStream ؛ استيراد java.io.ioException ؛ استيراد java.util.arraylist ؛ استيراد java.util.list ؛ استيراد com.shun.studentProto.student ؛ استيراد com.shun.teacherproto.teacher ؛ protowRiteTeTest الطبقة العامة {الحجم النهائي الثابت العام = 100 ؛ إلقاء Main Static Void Main (String []] args) IOException {// إنشاء قائمة قائمة <Tudture> StercuilderList = New ArrayList <Tudent> () ؛ لـ (int i = 0 ؛ i <size ؛ i ++) {student.builder levuilder = student.newbuilder () ؛ الحفل. الحفل. levuilder.setName ("Shun") ؛ Stervuilderlist.add (levuilder.build ()) ؛ } Teacher.Builder TeaBuilder = teacher.newbuilder () ؛ Teabuilder.setid (1) ؛ teabuilder.setName ("testtea") ؛ teabuilder.addallstudentList (stervuilderlist) ؛ // اكتب gpb إلى ملف fileOutputStream fos = جديد fileOutputStream ("c: // user // shun // desktop // test // proto-" + size) ؛ Teabuilder.build (). Writeto (FOS) ؛ fos.close () ؛ }} </span> يتم تغيير الحجم هنا إلى رقم الاختبار الذي قلناه أعلاه ، ويمكنك الحصول على ما يلي:
ثم دعونا نلقي نظرة على رمز اختبار JSON:
حزمة com.shun.test ؛ استيراد java.io.filewriter ؛ استيراد java.io.ioException ؛ استيراد java.util.arraylist ؛ استيراد java.util.list ؛ استيراد com.google.gson.gson ؛ استيراد com.shun.student ؛ استيراد com.shun.teacher ؛ الطبقة العامة gsonwritetest {public static final int = 100 ؛ Public Static Void Main (String [] args) يلقي iOexception {List <Stath> Stulist = new ArrayList <Tudent> () ؛ لـ (int i = 0 ؛ i <size ؛ i ++) {student stu = new student () ؛ Stu.Setage (25) ؛ Stu.SetID (22) ؛ Stu.SetName ("Shun") ؛ Stulist.add (Stu) ؛ } المعلم المعلم = معلم جديد () ؛ المعلم. Teacher.setName ("Shun") ؛ المعلم. النتيجة السلسلة = GSON () FILEWRITER FW = FILEWRITER جديد ("C: // user // shun // desktop // test // json" + size) ؛ fw.write (نتيجة) ؛ fw.close () ؛ }} </span> يتم استخدام نفس الطريقة لتعديل الحجم وإجراء الاختبارات المقابلة.
يمكن أن نرى بوضوح أن حجم ملف JSON و GPB سيكون له فرق كبير عند زيادة حجم البيانات تدريجياً. من الواضح أن JSON أكبر بكثير.
يجب أن يكون الجدول أعلاه أكثر وضوحًا. GPB من البيانات الكبيرة مهيمنة للغاية ، ولكن بشكل عام ، لن يتفاعل العميل والخادم مباشرة مع هذه البيانات الكبيرة. تحدث البيانات الضخمة بشكل أساسي في نقل الخادم. إذا واجهت الاحتياجات ، فأنت بحاجة إلى نقل مئات من ملفات السجل إلى خادم آخر كل يوم ، فقد يكون GPB هنا مساعدة كبيرة.
يقال إنها مقارنة بعمق ، لكن المقارنة الرئيسية هي الحجم ، ومقارنة الوقت ليست أكثر من اللازم ، ولا يوجد فرق كبير.
بالنسبة إلى GSON Parser المحدد في المقالة ، يمكن للأصدقاء المهتمين اختيار Jackson أو Fastjson ، أو غيره ، ولكن حجم الملف الذي تم إنشاؤه هو نفسه ، لكن وقت التحليل مختلف.