跳到主要內容

GSON基礎教學

GSON 前言

JSON是很常見的資料交換格式,在JAVA領域常用處理JSON的函式庫:GSON、FastXML和JSON-B,本章節會以GSON為主,學習目標如下

  • JSON格式說明
  • GSON 套件函式
  • GSON: 物件轉換JSON字串
  • GSON: JSON字串轉換物件

JSON 格式說明

JSON全名為JavaScript Object Notation,它是一種輕量級的資料交換格式,會大為流行的理由,主要是他比傳統用xml更輕巧且容易處理,JSON表達方式物件會用大括弧{},陣列則是用中括號[]。
用JSON字串來表達Employee的物件內容,由JSON字串可以知道物件name、age、sex和salary屬性。

JSON表示員工資料方式:
{“name”:”Jack Bryant”, “age”:18, “sex”:”M”,”salary”:3500.00}

JSON陣列表示方式:
跟我們使用JAVA的陣列方式類似,內容值可以是數字’、文字、布林、陣列、物件、null等等。
範例:
字串: [“紅”、”橙”、”黃”、”綠”、”青”、”藍”、”紫”}
布林: [true, true, false, false, true, true]

GSON 套件函式

Gson為google所發布的函式庫,主要將物件與json字串之間的轉換時方便使用。當我們將JAVA物件轉換成JSON字串稱為序列化,JSON字串轉換至JAVA物件稱為反序列化

enter image description here

GSON: 物件轉換JSON字串

有了JSON基本概念後,我們進入本章重點,首先我們需要建立員工類別(Employee),定義如下

物件 屬性
員工類別 Employee name 名字
age 年紀
sex 性別
salary 薪水
/**
 *  name:員工類別
 */
public class Employee implements Serializable {
    //constructor
    public  Employee(String name, double salary){
        this.name = name;
        this.salary = salary;
    }

    // employ's attribute
    private String name ;
    private int age ;
    private String sex;
    private double salary ;

    //setter and getter
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer() ;
        sb.append("") ;
        sb.append("name:"+name) ;
        sb.append("age:"+age) ;
        sb.append("sex:"+sex) ;
        sb.append("salary:"+salary) ;
        sb.append("") ;
        return sb.toString() ;
    }
   }

完成員工類別後,實際建立一個employee01 的物件,在使用Gson之前需要宣告Gson建構子,範例不管單數還是多數的物件,都是利用同一個toJson()方法來完成序列化轉成JSON字串,所使用起來相當方便。由結果可以發現兩件事情,一、我們發現單數和多數Json字串不同,多數物件顯示會有中括號[物件1、物件2]包括,但是單數沒有。二、Json字串缺少顯示sex屬性值,其將sex屬性列印出來後發現為null值,表示Gson會預先將屬性值為null的預先過濾掉後,才轉成JSON字串。這種方式並不會影響之後反序列處理。後續會有更詳細的Gson字串處理介紹

     /**
 * name : 員工轉json字串測試
 */
public class EmployeeTest {

    public static  void main(String[] arg){
               //單筆
        Employee employee01 = new Employee("bryan",30000);
        Employee employee02 = new Employee("joe",31000);
        employee02.setSex("N");
        Gson gson =  new Gson();
        String jsonStr1 = gson.toJson(employee01);
        String jsonStr2 = gson.toJson(employee01,Employee.class);
        System.out.println("jsonStr1:"+jsonStr1);
        System.out.println("jsonStr2:"+jsonStr2);

        //多筆
        List list = new ArrayList();
        list.add(employee01) ;
        list.add(employee02) ;
        String jsonStr3 = gson.toJson(list);
        System.out.println("jsonStr3:"+jsonStr3);

    }
}

結果:
jsonStr1:{“name”:”bryan”,”age”:0,”salary”:30000.0}
jsonStr2:{“name”:”bryan”,”age”:0,”salary”:30000.0}
jsonStr3:[{“name”:”bryan”,”age”:0,”salary”:30000.0},{“name”:”joe”,”age”:0,”sex”:”N”,”salary”:31000.0}]

物件關係表達

接下來我們將物件關係也加入,看Gson是否可以順利轉換成正確JSON字串,首先我們新增兩個物件:書明細(Book)和借書訂單(Order),之間的關係為員工借書會點選借書訂單系統,去挑選他的書明細,該系統會記錄該員工的姓名以及他點選書單的明細。

物件 屬性
書明細 Book bid 書單號
title書名稱
author 作者
借書訂單 Order orderId 訂單編號
employName 員工名稱
date 日期
bookList 書明細資料
/**
 * name : 書明細
 */
public class Book {
    private String bid;
    private String title;
    private String author;

    public Book(String bid, String title, String author)  {
        this.bid = bid ;
        this.title = title ;
        this.author = author ;
    }
    //setter and getter
    public String getBId() {
        return bid;
    }

    public void setBId(String id) {
        this.bid = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer() ;
        sb.append("") ;
        sb.append("bid:"+bid) ;
        sb.append("title:"+title) ;
        sb.append("author:"+author) ;
        sb.append("") ;
        return sb.toString() ;
    }

}

/**
 * name : 借書訂單
 */
public class Order {
    private String orderId;
    private String employName;
    private Date date;
    private List bookList;
    public Order(String orderId, String employName, Date date,
                 List bookList) {
        super();
        this.orderId = orderId;
        this.employName = employName;
        this.date = date;
        this.bookList = bookList;
    }

    //setter and getter
    public String getOrderId() {
        return orderId;
    }

    public void setOrderId(String orderId) {
        this.orderId = orderId;
    }

    public String getEmployName() {
        return employName;
    }

    public void setEmployName(String employName) {
        this.employName = employName;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public List getBookList() {
        return bookList;
    }

    public void setBookList(ArrayList bookList) {
        this.bookList = bookList;
    }

    public void show() {
        System.out.println("Order information:");
        System.out.println("orderId = " + orderId + "; employName = " + employName
                + "; date = " + date);
        System.out.println("Details: ");
        System.out.println(bookList.toString());
    }
}

employee01藉兩本書分別編號為B0001和B0002,這兩本書,我們把它加入oreder建構子中,再由Gson轉換成JSON字串出來,由結果顯示可以知道該訂單借了幾本書和是哪位員工借走。

/**
 * name : 借書訂單轉json字串測試
 */
public class OrderTest {

    public static  void main(String[] arg){
        //單筆
        Employee employee01 = new Employee("bryan",30000);
        Employee employee02 = new Employee("joe",31000);
        Book book01 = new Book("B0001","水滸傳","施耐庵 ") ;
        Book book02 = new Book("B0002","西遊記","吳承恩 ") ;
        Book book03 = new Book("B0003","三國演義","羅貫中 ") ;
        Book book04 = new Book("B0004","紅樓夢","曹雪芹 ") ;
        List bList = new ArrayList

JSON字串轉換物件

之前員工建立的Json字串,現在介紹如何用Gson來反序列Employee物件,有範例可以知道,Gson幾行就可以將JSON轉成物件化,用起來相當方便。

範例: JSON字串: {“name”:”bryan”,”age”:0,”salary”:30000.0}

/**
 * name: Json to Object 反序列範例
 */
public class EmployeeSTest {

    public static void main(String[] ags){
        Gson gson = new Gson();
        String employ_json = "{\"name\":\"bryan\",\"age\":0,\"salary\":30000.0}" ;
        Employee employee01 =  gson.fromJson(employ_json, Employee.class) ;
        System.out.println(employee01.toString());

    }
}

再來我們試看看List串列看看,是否可以也是跟上面宣告多數的物件相同,複數物件反序列比較麻煩一點,因為反序列需要告訴預先要轉換哪種類別,利用new TypeToken的方式來取得類別的類型,再使用fromJson方法轉回List<Employee>類型。
問題延伸: 但如果遇到泛型要如何解決?

Json字串: [{“name”:”bryan”,”age”:0,”salary”:30000.0},{“name”:”joe”,”age”:0,”sex”:”N”,”salary”:31000.0}]

/**
 * name: Json to Object 反序列範例
 */
public class EmployeeSTest {

    public static void main(String[] ags){
        Gson gson = new Gson();
        String employ_json = "{\"name\":\"bryan\",\"age\":0,\"salary\":30000.0}" ;
        Employee employee01 =  gson.fromJson(employ_json, Employee.class) ;
        System.out.println(employee01.toString());
        System.out.println("=========================List===========================");
        String employs_json = "[{\"name\":\"bryan\",\"age\":0,\"salary\":30000.0},{\"name\":\"joe\",\"age\":0,\"sex\":\"N\",\"salary\":31000.0}]";
        Type collectionType = new TypeToken

參考資料

  1. https://bng86.gitbooks.io/android-third-party-/content/gson.html
  2. http://j796160836.pixnet.net/blog/post/30530326-%E7%9E%AD%E8%A7%A3json%E6%A0%BC%E5%BC%8F
  3. http://blog.csdn.net/zzp_403184692/article/details/8266575

留言

這個網誌中的熱門文章

JavaBean 和POJO

前言 今天介紹JavaBean和POJO的不同,這兩個名詞在JAVA文章常常被拿來使用以及討論。在JDK1.1時候釋出才有的一個標準架構,很多時候常常被搞混,所以我們特別開闢一章來加以討論。POJO規範在企業級應用已經廣大的被使用的規範。 解釋 POJO : 全名為Plain-old-Java-object,只需要繼承Object就可以,沒有特定規定,只要建立的類別有setter/getter方法都可以稱為POJO JavaBean: JavaBean通常用來封裝多個物件成為單獨物件使用,規範比較嚴格,規則如下 規則 說明 1 需要實作序列(Serializable/Externalizable) 2 不能有參數的建構子( no-arg constructor) 3 需要有公用setter/getter 4 屬性必須要私人(private) 5 屬於特定POJO規則 比較 所有的JavaBean都為POJO,但是所有的POJO不一定為JavaBean 都可以當作重複元件 都必須序列化 特性都為可用性、易用性和持久化使用 - 應用 由圖我們可以知道POJO在應用程式中,主要用來存取資料庫資料達到持久化的目的,並提供給商業邏輯流程處理使用。這種POJO的架構提供程式人員開發時的可以很有規則將資料封裝並加以使用。 範例1. JavaBean(以員工為實例) JavaBean建立員工物件,可以發現Employee物件建構子沒有任何參數,屬性為私有化並setter/getter的命名方式。 //實作序列化 public class Employee implements java.io.Serializable{ private int id; private String name; //無參數建構子 public Employee(){} //以下實作setter/getter public void setId(int id){this.id=id;} public int getId(){return id;} public void setName(String ...

Python AI-手寫辨識

Python AI-手寫辨識 類神經網路-手寫辨識 手寫辨識 (1) 問題定義 將輸入手寫數字圖片,經由類神經網路訓練後,可以辨識手寫圖片得到一個正確的答案,例如讓電腦辨識上面圖片手寫數字0-9,都可以認得.在了解問題後,需要先知道輸入的資料格式,例如圖片為NxN的矩陣向量. 輸入:輸入的資料格式有很多種,例如數字圖片為矩陣向量 模型:NN 輸出:輸出的方式,神經網路輸出不一定跟輸入同值,手寫數字輸入為1,輸出有可能是1.1或是1.5等等,所以輸出必須經過轉換成真實世界的數字. (2)定義函式 輸出會有兩個問題: A.輸出利用one-hot encoding來表示,就是N個狀態會對應N的結果,例如:輸出結果為1,表示[0,1,0,0,0,0,0,0,0,0] B.輸出結果不能超過1,我們通常會利用 Softmax函数 來進行輸出的處理. (3) 準備訓練/測試資料 在這邊需要從輸入去定義那些要當作訓練與測試資料,我們手寫資料使用MNIST 資料庫來訓練使用,MNIST共有70,000筆手寫資料,60,000筆為訓練資料,10,000為測試資料. (4)建構類神經網路模型 開始建構我們的神經網路模型,首先決定好28x28的像素(這邊不用擔心如何將圖片轉成矩陣),模型使用SGD的方式進行學習,輸出是一個10為的陣列來表示. 輸入:手寫數字圖片(28x28=784) 模型:SGD 輸出:數字(one hard encoding) (5)學習 首先介紹SGD(Stochastic Gradient Descent) 的學習方式,因為蕾神經網路需要訓練很多次才會提高準確度,SGD最大的好處就是當每次重新學習的會將訓練資料打散,來防止機器學習將答案死背下來. (6)實作開發 下面程式碼有完整的說明,這邊就不多說明了,當開始執行程式時就會進行資料訓練. 由訓練結果最後acc=0.9447,表示準確率可以到達94%,我們再由實際測試可以看出該圖為7的圖示,由神經網路判斷為7,跟我們人類判斷相同,我們可以知道由訓練的結果可看得到不錯的準確度. 執行神經網路遇到不少問題,請參考下面連結,是筆者所整理的問題集,請多多指教 https://programdoubledragon.bl...

Python AI-問題集

Python AI-問題集 問題集 Jupyter Notebook執行ipywidgets會出現kernel死掉的錯誤發生(The kernel appears to have died) 解決方法 (1) 根據log檔來判斷問題: 例如:log訊息出現OMP: Error #15: Initializing libiomp5.dylib, but found libiomp5.dylib already initialized. (2) 根據問題關鍵字找出問題所在: 利用google查詢所遭遇到的問題,例如我把上面的問題上google查詢可以找到這篇的解法 https://blog.csdn.net/bingjianIT/article/details/86182096 (3)實作解法: 我實作下面解法後,就可以順利執行手寫辨識的程式. //在Python宣告時加入 import os os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE" 參考 https://blog.csdn.net/bingjianIT/article/details/86182096