首頁 > 軟體

Jackson中json格式的字串與物件的互相轉換方式

2022-07-05 18:06:31

json格式的字串與物件的互相轉換

Jackson 簡介

Jackson是一個簡單基於Java應用庫,Jackson可以輕鬆的將Java物件轉換成json字串和xml檔案,同樣也可以將json、xml轉換成Java物件。Jackson所依賴的jar包較少,簡單易用並且效能也要相對高些,並且Jackson社群相對比較活躍,更新速度也比較快。

jackson特點

  • 容易使用 - jackson API提供了一個高層次外觀,以簡化常用的用例。
  • 無需建立對映 - API提供了預設的對映大部分物件序列化。
  • 效能高 - 快速,低記憶體佔用,適合大型物件圖表或系統。
  • 乾淨的JSON - jackson建立一個乾淨和緊湊的JSON結果,這是讓人很容易閱讀。
  • 不依賴 - 庫不需要任何其他的庫,除了JDK。
  • 開原始碼 - jackson是開源的,可以免費使用。

json格式的字串與物件的轉換

使用Jackson必須要在專案匯入對應的jar包。

Book.java檔案

package cn.hestyle.bean;
public class Book {
	private String id;
	private String name;
	private double price;
	private int pnum;
	private String category;
	private String description;
	
	public Book() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Book(String id, String name, double price, int pnum, String category, String description) {
		super();
		this.id = id;
		this.name = name;
		this.price = price;
		this.pnum = pnum;
		this.category = category;
		this.description = description;
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public double getPrice() {
		return price;
	}
	public void setPrice(double price) {
		this.price = price;
	}
	public int getPnum() {
		return pnum;
	}
	public void setPnum(int pnum) {
		this.pnum = pnum;
	}
	public String getCategory() {
		return category;
	}
	public void setCategory(String category) {
		this.category = category;
	}
	public String getDescription() {
		return description;
	}
	public void setDescription(String description) {
		this.description = description;
	}
	@Override
	public String toString() {
		return "Book [id=" + id + ", name=" + name + ", price=" + price + ", pnum=" + pnum + ", category=" + category
				+ ", description=" + description + "]";
	}
}
package cn.hestyle.utils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import cn.hestyle.bean.Book;
public class JacksonDemo01 {
	public static void main(String[] args) throws JsonGenerationException, JsonMappingException, IOException {
		ObjectMapper objectMapper = new ObjectMapper();
		//將物件轉換為json格式的字串
		Book book = new Book("1001", "Java入門到入土", 99.9, 100, "程式設計開發", "你懂得!");
		String bookJsonStr = objectMapper.writeValueAsString(book);
		System.out.println(bookJsonStr);
		//將集合、陣列物件轉換為json格式的字串
		List<Book> bookList = new ArrayList<Book>();
		bookList.add(new Book("1001", "Java入門到入土", 99.9, 100, "程式設計開發", "你懂得!"));
		bookList.add(new Book("1002", "Python入門到入土", 89.9, 100, "程式設計開發", "你懂得!"));
		bookList.add(new Book("1003", "C++入門到入土", 89.9, 200, "程式設計開發", "你懂得!"));
		String bookListJsonStr = objectMapper.writeValueAsString(bookList);
		System.out.println(bookListJsonStr);
		
		//將json格式的字串轉化為物件
		//字串中含有雙引號,需要使用反斜槓跳脫
		String bookString = "{"id":"1001","name":"Java入門到入土","price":99.9,"pnum":100}";
		//Book必須有無參的構造方法
		Book book2 = objectMapper.readValue(bookString, Book.class);
		System.out.println(book2);
	}
}

控制檯輸出:

Jackson進行json轉物件,物件轉json總結

在前後端分離的專案中,後端經常涉及到json與物件互轉的場景。阿里巴巴的Fastjson是好用,但是,因為技術領導的原因(可能因為fastjson1的各種問題很多吧),不讓用,所以就需要選擇其他技術棧。當前比較常用的是SpringBoot自帶的Jackson或者谷歌的Gson。

下面,做一下使用Jackson的總結。

JavaBean準備

1.Company,公司

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Company {
    private String companyName;
    private List<WebSite> webSites;
}

2.WebSite,站點

@Data
@NoArgsConstructor
@AllArgsConstructor
public class WebSite {
    private String webSiteName;
    private List<User> users;
}

3.User,使用者

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private String userId;
    private String username;
    private String password;
}

json字串和物件互轉

物件轉json字串

不管你是什麼結構的物件,想轉json,直接objectMapper.writeValueAsString()搞定。

    /**
     * 序列化:物件轉json字串,包含多個陣列
     *
     */
    @Test
    public void testObject2Json2() {
        User user2 = new User("1","上海闢謠專屬隊","職業闢謠,不信謠,不傳謠,呵呵");
        List<User> users = new ArrayList<>();
        users.add(user2);
        WebSite webSite = new WebSite();
        webSite.setWebSiteName("xxxxxx.com");
        webSite.setUsers(users);
        List<WebSite> webSites = new ArrayList<>();
        webSites.add(webSite);
        Company company = new Company();
        company.setCompanyName("yyyyyy");
        company.setWebSites(webSites);
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            String jsonString = objectMapper.writeValueAsString(company);
            System.out.println(jsonString);
        } catch (JsonProcessingException e) {
            log.error("error: ", e);
        }
    }

輸出:

{"companyName":"yyyyyy","webSites":[{"webSiteName":"xxxxxx.com","users":[{"userId":"1","username":"上海闢謠專屬隊","password":"職業闢謠,不信謠,不傳謠,呵呵"}]}]}

json字串轉物件

注意:這種情形是json物件字串,不能是json陣列字串,後面會說到。

    @Test
    public void testJson2Object() {
        String json = "{"companyName":"yyyyyy","webSites":[" +
                "{"webSiteName":"xxxxxx.com","users":[{"userId":"1","username":"上海闢謠專屬隊","password":"職業闢謠,不信謠,不傳謠,呵呵"}]}" +
                "]}";
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            Company company = objectMapper.readValue(json, Company.class);
            System.out.println(company.getWebSites().get(0).getUsers().get(0).getUsername());
        } catch (JsonProcessingException e) {
            log.error("error: ", e);
        }
    }

輸出:

上海闢謠專屬隊

json陣列字串和陣列(集合)物件互轉

有個大坑

陣列物件轉json陣列字串

    /**
     * 序列化:陣列物件轉json陣列型別的字串
     *
     */
    @Test
    public void testObjectArray2JsonArrayString() {
        User user1 = new User("1","上海帶刀滬衛","帶刀大佬");
        User user2 = new User("1","上海闢謠專屬隊","職業闢謠,不信謠,不傳謠,呵呵");
        List<User> users = new ArrayList<>();
        users.add(user1);
        users.add(user2);
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            String json = objectMapper.writeValueAsString(users);
            System.out.println(json);
        } catch (JsonProcessingException e) {
            log.error("error: ", e);
        }
    }

輸出:

[{"userId":"1","username":"上海帶刀滬衛","password":"帶刀大佬"},{"userId":"1","username":"上海闢謠專屬隊","password":"職業闢謠,不信謠,不傳謠,呵呵"}]

json陣列字串轉陣列物件

先演示一下錯誤的寫法先演示一下錯誤的寫法先演示一下錯誤的寫法,重要的事情說三遍!

    /**
     * 反序列化:陣列型別的json字串轉物件陣列
     *
     */
    @Test
    public void testJsonArrayString2ObjectArray() {
        String json = "[" +
                "{"userId":"1","username":"上海帶刀滬衛","password":"帶刀大佬"}" +
                ",{"userId":"1","username":"上海闢謠專屬隊","password":"職業闢謠,不信謠,不傳謠,呵呵"}" +
                "]";
        ObjectMapper objectMapper = new ObjectMapper();
        try {
			//錯誤寫法
            List<User> list = objectMapper.readValue(json, List.class);
            list.forEach(user -> {
                System.out.println(user.getUsername());
            });
        } catch (JsonProcessingException e) {
            log.error("error: ", e);
        }
    }

輸出異常


java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.xywei.springboot.springtestdemo.entity.User

    at java.util.ArrayList.forEach(ArrayList.java:1259)
    at com.xywei.springboot.springtestdemo.junit.TestUseJackson.testJsonArrayString2ObjectArray(TestUseJackson.java:160)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688)
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    at 

#省略大段……
Process finished with exit code -1

因為實際轉成了map型別,所以使用List方式取值是錯的!

正確做法:

    /**
     * 反序列化:陣列型別的json字串轉物件陣列
     *
     */
    @Test
    public void testJsonArrayString2ObjectArray() {
        String json = "[" +
                "{"userId":"1","username":"上海帶刀滬衛","password":"帶刀大佬"}" +
                ",{"userId":"1","username":"上海闢謠專屬隊","password":"職業闢謠,不信謠,不傳謠,呵呵"}" +
                "]";
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            TypeReference<List<User>> typeReference = new TypeReference<List<User>>() {
            };
            List<User> list = objectMapper.readValue(json, typeReference);
            list.forEach(user -> {
                System.out.println(user.getUsername());
            });
        } catch (JsonProcessingException e) {
            log.error("error: ", e);
        }
    }

最終輸出:

上海帶刀滬衛

上海闢謠專屬隊

同時,對多層巢狀的陣列也適用:

    @Test
    public void testJsonArrayString2ObjectArray2() {
        String json = "[" +
                    "{" +
                    ""companyName":"yyyyyy","webSites":[" +
                            "{"webSiteName":"xxxxxx.com","users":[" +
                                "{"userId":"1","username":"上海闢謠專屬隊","password":"職業闢謠,不信謠,不傳謠,呵呵"}" +
                                "]" +
                            "}" +
                        "]" +
                    "}" +
                "]";
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            TypeReference<List<Company>> typeReference = new TypeReference<List<Company>>() {
            };
            List<Company> list = objectMapper.readValue(json, typeReference);
            list.forEach(company -> {
                System.out.println(company.getWebSites().get(0).getUsers().get(0).getUsername());
            });
        } catch (JsonProcessingException e) {
            log.error("error: ", e);
        }
    }

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com