محلل جاكسون جيسون جافا شهير للغاية ويستخدم في إطار Spring أيضًا. واجهة برمجة تطبيقات جافا لمعالجة JSON ليست ودية للمستخدم بشكل كبير ولا توفر ميزات للتحويل التلقائي من Json إلى كائن Java والعكس. لحسن الحظ لدينا بعض واجهات البرمجة البديلة التي يمكننا استخدامها لمعالجة JSON. في المقالة الأخيرة، تعلمنا عن واجهة برمجة تطبيقات جوغل جسون ورأينا مدى سهولة استخدامها.
محلل جاكسون جيسون جافا
لاستخدام واجهة برمجة جاكسون جيسون جافا في مشروعنا، يمكننا إضافتها إلى مسار بناء المشروع أو إذا كنت تستخدم مافن، يمكننا إضافة التبعية أدناه.
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.2.3</version>
</dependency>
جاكسون-داتابايند جار يعتمد على مكتبة جاكسون-كور و جاكسون-تعليقات، لذا إذا كنت تقوم بإضافتها مباشرة إلى مسار البناء، تأكد من أنك قمت بإضافة الثلاثة بخصوصها، وإلا ستحصل على خطأ في وقت التشغيل. توفر واجهة برمجة تطبيقات جاكسون لمعالجة JSON طريقة سهلة لتحويل JSON إلى كائن POJO وتدعم تحويلًا سهلاً إلى Map من بيانات JSON. تدعم جاكسون الجينيريكس أيضًا وتحولها مباشرة من JSON إلى كائن.
مثال جاكسون JSON
لمثالنا على تحويل JSON إلى POJO/كائن Java، سنأخذ مثالًا معقدًا يحتوي على كائن متداخل ومصفوفات. سنستخدم مصفوفات وقائمة و Map في كائنات Java للتحويل. يتم تخزين JSON المعقد لدينا في ملف employee.txt بالهيكل أدناه:
{
"id": 123,
"name": "Pankaj",
"permanent": true,
"address": {
"street": "Albany Dr",
"city": "San Jose",
"zipcode": 95129
},
"phoneNumbers": [
123456,
987654
],
"role": "Manager",
"cities": [
"Los Angeles",
"New York"
],
"properties": {
"age": "29 years",
"salary": "1000 USD"
}
}
لدينا فئات Java التالية تتوافق مع بيانات JSON.
package com.journaldev.jackson.model;
public class Address {
private String street;
private String city;
private int zipcode;
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public int getZipcode() {
return zipcode;
}
public void setZipcode(int zipcode) {
this.zipcode = zipcode;
}
@Override
public String toString(){
return getStreet() + ", "+getCity()+", "+getZipcode();
}
}
تتوافق فئة العنوان مع الكائن الداخلي في بيانات JSON الجذر.
package com.journaldev.jackson.model;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public class Employee {
private int id;
private String name;
private boolean permanent;
private Address address;
private long[] phoneNumbers;
private String role;
private List<String> cities;
private Map<String, String> properties;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isPermanent() {
return permanent;
}
public void setPermanent(boolean permanent) {
this.permanent = permanent;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public long[] getPhoneNumbers() {
return phoneNumbers;
}
public void setPhoneNumbers(long[] phoneNumbers) {
this.phoneNumbers = phoneNumbers;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
@Override
public String toString(){
StringBuilder sb = new StringBuilder();
sb.append("***** Employee Details *****\n");
sb.append("ID="+getId()+"\n");
sb.append("Name="+getName()+"\n");
sb.append("Permanent="+isPermanent()+"\n");
sb.append("Role="+getRole()+"\n");
sb.append("Phone Numbers="+Arrays.toString(getPhoneNumbers())+"\n");
sb.append("Address="+getAddress()+"\n");
sb.append("Cities="+Arrays.toString(getCities().toArray())+"\n");
sb.append("Properties="+getProperties()+"\n");
sb.append("*****************************");
return sb.toString();
}
public List<String> getCities() {
return cities;
}
public void setCities(List<String> cities) {
this.cities = cities;
}
public Map<String, String> getProperties() {
return properties;
}
public void setProperties(Map<String, String> properties) {
this.properties = properties;
}
}
الموظف هو جافا بين يمثل كائن JSON الجذر. الآن دعونا نرى كيف يمكننا تحويل JSON إلى كائن Java باستخدام واجهة برمجة تطبيقات جاكسون لمعالجة JSON.
package com.journaldev.jackson.json;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.journaldev.jackson.model.Address;
import com.journaldev.jackson.model.Employee;
public class JacksonObjectMapperExample {
public static void main(String[] args) throws IOException {
//قراءة بيانات ملف JSON إلى سلسلة
byte[] jsonData = Files.readAllBytes(Paths.get("employee.txt"));
//إنشاء مثيل ObjectMapper
ObjectMapper objectMapper = new ObjectMapper();
//تحويل سلسلة JSON إلى كائن
Employee emp = objectMapper.readValue(jsonData, Employee.class);
System.out.println("Employee Object\n"+emp);
//تحويل الكائن إلى سلسلة JSON
Employee emp1 = createEmployee();
//تكوين محول الكائن للطباعة الجميلة
objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true);
//الكتابة إلى وحدة التحكم، يمكن الكتابة إلى أي مخرج مثل ملف
StringWriter stringEmp = new StringWriter();
objectMapper.writeValue(stringEmp, emp1);
System.out.println("Employee JSON is\n"+stringEmp);
}
public static Employee createEmployee() {
Employee emp = new Employee();
emp.setId(100);
emp.setName("David");
emp.setPermanent(false);
emp.setPhoneNumbers(new long[] { 123456, 987654 });
emp.setRole("Manager");
Address add = new Address();
add.setCity("Bangalore");
add.setStreet("BTM 1st Stage");
add.setZipcode(560100);
emp.setAddress(add);
List cities = new ArrayList();
cities.add("Los Angeles");
cities.add("New York");
emp.setCities(cities);
Map props = new HashMap();
props.put("salary", "1000 Rs");
props.put("age", "28 years");
emp.setProperties(props);
return emp;
}
}
عند تشغيل البرنامج أعلاه، ستحصل على الناتج التالي.
Employee Object
***** Employee Details *****
ID=123
Name=Pankaj
Permanent=true
Role=Manager
Phone Numbers=[123456, 987654]
Address=Albany Dr, San Jose, 95129
Cities=[Los Angeles, New York]
Properties={age=29 years, salary=1000 USD}
*****************************
Employee JSON is
//طباعة نفس بيانات ملف json السابق
com.fasterxml.jackson.databind.ObjectMapper هو الفصل الأكثر أهمية في واجهة برمجة التطبيقات جاكسون الذي يوفر أساليب readValue() و writeValue() لتحويل JSON إلى كائن جافا و كائن جافا إلى JSON. يمكن إعادة استخدام الفصل ObjectMapper ويمكننا تهيئته مرة واحدة ككائن Singleton. هناك العديد من الإصدارات المتحملة لأساليب readValue() و writeValue() للعمل مع مصفوفة البايتات، الملف، مدخل/مخرج التيار، وكائنات القراءة/الكتابة.
Jackson JSON – تحويل JSON إلى Map
أحيانًا لدينا كائن JSON مثلما في الملف data.txt أدناه:
{
"name": "David",
"role": "Manager",
"city": "Los Angeles"
}
ونريد تحويله إلى Map وليس إلى كائن جافا بنفس الخصائص والمفاتيح. يمكننا فعل ذلك بسهولة جدًا في واجهة برمجة التطبيقات جاكسون JSON باستخدام طريقتين مع الكود أدناه:
//تحويل json إلى Map
byte[] mapData = Files.readAllBytes(Paths.get("data.txt"));
Map myMap = new HashMap();
ObjectMapper objectMapper = new ObjectMapper();
myMap = objectMapper.readValue(mapData, HashMap.class);
System.out.println("Map is: "+myMap);
//طريقة أخرى
myMap = objectMapper.readValue(mapData, new TypeReference>() {});
System.out.println("Map using TypeReference: "+myMap);
عند تنفيذ المقطع أعلاه، نحصل على الناتج التالي:
Map is: {name=David, role=Manager, city=Los Angeles}
Map using TypeReference: {name=David, role=Manager, city=Los Angeles}
Jackson JSON – قراءة مفتاح JSON محدد
أحيانًا لدينا بيانات JSON ونحن مهتمون فقط بقيم بعض المفاتيح، لذا في هذه الحالة تحويل ال JSON بأكمله إلى كائن ليس فكرة جيدة. توفر واجهة برمجة التطبيقات لـ Jackson JSON خيارًا لقراءة بيانات JSON كشجرة مثل محلل DOM ويمكننا قراءة عناصر محددة من كائن JSON من خلال هذا. يوفر الكود أدناه مقتطفًا لقراءة مدخلات محددة من ملف JSON.
//قراءة بيانات الملف ال JSON إلى سلسلة
byte[] jsonData = Files.readAllBytes(Paths.get("employee.txt"));
//إنشاء مثيل ObjectMapper
ObjectMapper objectMapper = new ObjectMapper();
//قراءة JSON مثل محلل DOM
JsonNode rootNode = objectMapper.readTree(jsonData);
JsonNode idNode = rootNode.path("id");
System.out.println("id = "+idNode.asInt());
JsonNode phoneNosNode = rootNode.path("phoneNumbers");
Iterator elements = phoneNosNode.elements();
while(elements.hasNext()){
JsonNode phone = elements.next();
System.out.println("Phone No = "+phone.asLong());
}
نحصل على الناتج التالي عند تنفيذ مقتطف الكود أعلاه.
id = 123
Phone No = 123456
Phone No = 987654
Jackson JSON – تحرير مستند JSON
توفر واجهة برمجة التطبيقات Java لـ Jackson JSON أساليب مفيدة لإضافة وتحرير وإزالة المفاتيح من بيانات JSON وبعد ذلك يمكننا حفظها كملف JSON جديد أو كتابتها في أي تيار. يوضح الكود أدناه لنا كيفية القيام بذلك بسهولة.
byte[] jsonData = Files.readAllBytes(Paths.get("employee.txt"));
ObjectMapper objectMapper = new ObjectMapper();
//إنشاء JsonNode
JsonNode rootNode = objectMapper.readTree(jsonData);
//تحديث بيانات JSON
((ObjectNode) rootNode).put("id", 500);
//إضافة قيمة مفتاح جديدة
((ObjectNode) rootNode).put("test", "test value");
//إزالة المفتاح الحالي
((ObjectNode) rootNode).remove("role");
((ObjectNode) rootNode).remove("properties");
objectMapper.writeValue(new File("updated_emp.txt"), rootNode);
إذا قمت بتنفيذ الكود أعلاه وبحثت عن الملف الجديد، ستلاحظ أنه لا يحتوي على مفتاحي “الدور” و “الخصائص”. ستلاحظ أيضًا أن قيمة “المعرف” تم تحديثها إلى 500 وتمت إضافة مفتاح جديد “اختبار” إلى ملف updated_emp.txt المُحدث.
مثال على واجهة برمجة تطبيقات جاكسون JSON Streaming
تقدم واجهة برمجة تطبيقات جاكسون JSON Java دعمًا للتدفق الذي يكون مفيدًا في التعامل مع بيانات JSON الكبيرة لأنه يقوم بقراءة الملف بأكمله كرموز ويستخدم أقل من ذاكرة. المشكلة الوحيدة مع واجهة التدفق هي أنه يجب علينا أن نعتني بجميع الرموز أثناء تحليل بيانات JSON. إذا كانت لدينا بيانات JSON على النحو التالي: { “role”: “مدير” }، فسنحصل على الرموز التالية بالترتيب – { (بداية الكائن)، “role” (اسم المفتاح)، “مدير” (قيمة المفتاح)، و} (نهاية الكائن). الفاصلة (:) هي الفاصلة في JSON وبالتالي لا تعتبر رمزًا.
package com.journaldev.jackson.json;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.journaldev.jackson.model.Address;
import com.journaldev.jackson.model.Employee;
public class JacksonStreamingReadExample {
public static void main(String[] args) throws JsonParseException, IOException {
// إنشاء كائن JsonParser
JsonParser jsonParser = new JsonFactory().createParser(new File("employee.txt"));
// تكرار خلال الرموز
Employee emp = new Employee();
Address address = new Address();
emp.setAddress(address);
emp.setCities(new ArrayList());
emp.setProperties(new HashMap());
List phoneNums = new ArrayList();
boolean insidePropertiesObj=false;
parseJSON(jsonParser, emp, phoneNums, insidePropertiesObj);
long[] nums = new long[phoneNums.size()];
int index = 0;
for(Long l :phoneNums){
nums[index++] = l;
}
emp.setPhoneNumbers(nums);
jsonParser.close();
// طباعة كائن الموظف
System.out.println("Employee Object\n\n"+emp);
}
private static void parseJSON(JsonParser jsonParser, Employee emp,
List phoneNums, boolean insidePropertiesObj) throws JsonParseException, IOException {
// تكرار من خلال رموز Json
while(jsonParser.nextToken() != JsonToken.END_OBJECT){
String name = jsonParser.getCurrentName();
if("id".equals(name)){
jsonParser.nextToken();
emp.setId(jsonParser.getIntValue());
}else if("name".equals(name)){
jsonParser.nextToken();
emp.setName(jsonParser.getText());
}else if("permanent".equals(name)){
jsonParser.nextToken();
emp.setPermanent(jsonParser.getBooleanValue());
}else if("address".equals(name)){
jsonParser.nextToken();
// كائن متداخل، استدعاء متكرر
parseJSON(jsonParser, emp, phoneNums, insidePropertiesObj);
}else if("street".equals(name)){
jsonParser.nextToken();
emp.getAddress().setStreet(jsonParser.getText());
}else if("city".equals(name)){
jsonParser.nextToken();
emp.getAddress().setCity(jsonParser.getText());
}else if("zipcode".equals(name)){
jsonParser.nextToken();
emp.getAddress().setZipcode(jsonParser.getIntValue());
}else if("phoneNumbers".equals(name)){
jsonParser.nextToken();
while (jsonParser.nextToken() != JsonToken.END_ARRAY) {
phoneNums.add(jsonParser.getLongValue());
}
}else if("role".equals(name)){
jsonParser.nextToken();
emp.setRole(jsonParser.getText());
}else if("cities".equals(name)){
jsonParser.nextToken();
while (jsonParser.nextToken() != JsonToken.END_ARRAY) {
emp.getCities().add(jsonParser.getText());
}
}else if("properties".equals(name)){
jsonParser.nextToken();
while(jsonParser.nextToken() != JsonToken.END_OBJECT){
String key = jsonParser.getCurrentName();
jsonParser.nextToken();
String value = jsonParser.getText();
emp.getProperties().put(key, value);
}
}
}
}
}
JsonParser هو واجهة برمجة تطبيقات جاكسون لقراءة بيانات JSON بتقنية التدفق، نحن نستخدمها لقراءة البيانات من الملف ثم يتم استخدام طريقة parseJSON() لتكرار الرموز ومعالجتها لإنشاء كائن Java الخاص بنا. لاحظ أنه يتم استدعاء طريقة parseJSON() بشكل متكرر لـ “address” لأنها كائن متداخل في بيانات JSON. بالنسبة لتحليل المصفوفات، نكرر خلال مستند JSON. يمكننا استخدام فئة JsonGenerator لإنشاء بيانات JSON باستخدام واجهة التدفق.
package com.journaldev.jackson.json;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Set;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
import com.journaldev.jackson.model.Employee;
public class JacksonStreamingWriteExample {
public static void main(String[] args) throws IOException {
Employee emp = JacksonObjectMapperExample.createEmployee();
JsonGenerator jsonGenerator = new JsonFactory()
.createGenerator(new FileOutputStream("stream_emp.txt"));
// للطباعة الجميلة
jsonGenerator.setPrettyPrinter(new DefaultPrettyPrinter());
jsonGenerator.writeStartObject(); // start root object
jsonGenerator.writeNumberField("id", emp.getId());
jsonGenerator.writeStringField("name", emp.getName());
jsonGenerator.writeBooleanField("permanent", emp.isPermanent());
jsonGenerator.writeObjectFieldStart("address"); //start address object
jsonGenerator.writeStringField("street", emp.getAddress().getStreet());
jsonGenerator.writeStringField("city", emp.getAddress().getCity());
jsonGenerator.writeNumberField("zipcode", emp.getAddress().getZipcode());
jsonGenerator.writeEndObject(); //end address object
jsonGenerator.writeArrayFieldStart("phoneNumbers");
for(long num : emp.getPhoneNumbers())
jsonGenerator.writeNumber(num);
jsonGenerator.writeEndArray();
jsonGenerator.writeStringField("role", emp.getRole());
jsonGenerator.writeArrayFieldStart("cities"); //start cities array
for(String city : emp.getCities())
jsonGenerator.writeString(city);
jsonGenerator.writeEndArray(); //closing cities array
jsonGenerator.writeObjectFieldStart("properties");
Set keySet = emp.getProperties().keySet();
for(String key : keySet){
String value = emp.getProperties().get(key);
jsonGenerator.writeStringField(key, value);
}
jsonGenerator.writeEndObject(); //closing properties
jsonGenerator.writeEndObject(); //closing root object
jsonGenerator.flush();
jsonGenerator.close();
}
}
JsonGenerator يسهل استخدامه مقارنة بـ JsonParser. هذا كل شيء للإشارة السريعة إلى دروس تعليمية لـ Jackson JSON Parser Java API. تقدم واجهة برمجة تطبيقات Jackson JSON Java API سهولة الاستخدام وتوفر العديد من الخيارات لراحة المطورين الذين يعملون مع بيانات JSON. قم بتنزيل المشروع من الرابط أدناه وتجربته لاستكشاف المزيد من الخيارات حول واجهة برمجة تطبيقات Jackson Json.
المرجع: صفحة جيتهاب Jackson
Source:
https://www.digitalocean.com/community/tutorials/jackson-json-java-parser-api-example-tutorial