Jackson JSON Java Parser פופולרי מאוד ומשמש ב-Spring framework גם. Java JSON Processing API לא משתמש בידים ואינו מספק תכונות להמרה אוטומטית מ-Json לאובייקט Java ולהיפך. מזל טוב שיש לנו כמה API חלופיים שאפשר להשתמש בהם לעיבוד JSON. במאמר האחרון למדנו על Google Gson API וראינו כמה קל להשתמש בו.
Jackson JSON Java Parser
כדי להשתמש ב-Jackson JSON Java API בפרויקט שלנו, אנו יכולים להוסיף אותו לנתיב הבנייה של הפרויקט או אם אתה משתמש ב-maven, אנו יכולים להוסיף את התלות הבאה.
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.2.3</version>
</dependency>
jackson-databind תלוי בספריות jackson-core ו- jackson-annotations, לכן אם אתה מוסיף אותם ישירות לנתיב הבנייה, הקפיד להוסיף את כל שלוש, אחרת ייתכן שתקבל שגיאת ריצה. ממשק ה-JSON Parser של Jackson מספק דרך קלה להמיר JSON ל-POJO Object ותומך בהמרה קלה ל-Map מנתוני JSON. Jackson תומך גם ב- generics וממיר אותם ישירות מ-JSON ל-Object.
Jackson דוגמה ל-JSON
לדוגמה שלנו להמרת JSON ל-POJO/Java object, נקח דוגמה מורכבת עם אובייקטים מקוננים ומערכים. נשתמש במערכות, רשימות ו-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();
}
}
המחלקה Address תואמת לאובייקט הפנימי בנתוני ה-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;
}
}
Employee הוא ה- Java bean המייצג את אובייקט ה-JSON הראשי. עכשיו נראה איך ניתן להמיר JSON ל- java object באמצעות Jackson JSON parser API.
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);
//המר Object למחרוזת JSON
Employee emp1 = createEmployee();
//הגדר Object mapper להדפסה יפהפייה
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 היא המחלקה החשובה ביותר ב-API של Jackson שמספקת את השיטות readValue() ו-writeValue() על מנת להמיר JSON לאובייקט Java ו-אובייקט Java ל-JSON. המחלקה ObjectMapper יכולה להיות משומשת מחדש וניתן לאתחל אותה פעם אחת כאובייקט יחיד. יש כל כך הרבה גרסאות מוטעות של שיטות readValue() ו-writeValue() כדי לעבוד עם מערך בתים, קובץ, קלט/פלט ואובייקטי קורא/כותב.
Jackson JSON – המרת JSON למפת נתונים
לעיתים קרות שיש לנו אובייקט JSON כמו בקובץ data.txt:
{
"name": "David",
"role": "Manager",
"city": "Los Angeles"
}
ואנו רוצים להמיר אותו למפת נתונים ולא לאובייקט Java עם תכונות ומפתחות זהים. ניתן לעשות זאת בקלות רבה ב-API של Jackson JSON עם שתי שיטות עם הקוד הבא:
//המרת json למפת נתונים
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 API מספקת אפשרות לקריאת נתוני JSON כמו עץ בסגנון DOM Parser וניתן לקרוא אלמנטים מסוימים של אובייקט JSON דרך זה. הקוד הבא מספק קטע קוד לקריאת רשומות מסוימות מקובץ JSON.
//קרא נתוני קובץ JSON כמחרוזת
byte[] jsonData = Files.readAllBytes(Paths.get("employee.txt"));
//צור מופע ObjectMapper
ObjectMapper objectMapper = new ObjectMapper();
//קרא JSON כמו DOM Parser
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
ה-API של Jackson JSON בשפת Java מספק שיטות שימושיות להוספת, עריכה והסרת מפתחות מנתוני 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);
אם תפעיל את הקוד למעלה ותחפש את הקובץ החדש, תגלה שאין בו את המפתחים "role" ו-"properties". תגלה גם שהערך של "id" עודכן ל-500 ומפתח חדש בשם "test" נוסף לקובץ updated_emp.txt.
דוגמה ל- API הזרמת JSON של Jackson
ה- API של Jackson ל-Java JSON מספק גם תמיכה בזרימה שמועילה בעבודה עם נתוני JSON גדולים מכיוון שהוא קורא את כל הקובץ כאסימונים ומשתמש בפחות זיכרון. הבעיה היחידה עם API הזרמה היא שעלינו לטפל בכל האסימונים בעת פירוק נתוני ה- JSON. אם יש לנו נתוני JSON כגון { "תפקיד": "מנהל" } אז נקבל את האסימונים הבאים בסדר – { (תחילת אובייקט), "תפקיד" (שם מפתח), "מנהל" (ערך מפתח) ו- } (סוף אובייקט). הנקודתיים (:) הם המפרידים ב- 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 {
// לולאה דרך ה- JsonTokens
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 הוא API הזרמת JSON של Jackson לקריאת נתוני JSON, אנו משתמשים בו כדי לקרוא נתונים מהקובץ ולאחר מכן באמצעות השיטה parseJSON() אנו משתמשים לעבור דרך האסימונים ולעבד אותם כדי ליצור את אובייקט ה-Java שלנו. שימו לב שהשיטה parseJSON() נקראת רקורסיבית עבור "כתובת" מכיוון שהיא אובייקט מקונן בנתוני ה- JSON. לפירוק מערכים, אנו עוברים דרך מסמך ה- JSON. ניתן להשתמש במחלקת JsonGenerator כדי ליצור נתוני JSON עם API הזרמה.
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 API.
הפנייה: עמוד ה-GitHub של Jackson
Source:
https://www.digitalocean.com/community/tutorials/jackson-json-java-parser-api-example-tutorial