[Bài 12] Convert json sang POJO

I. Mở bài

Có nhiều TH chúng ta muốn lấy thông tin từ json của response, chúng ta có thể

  • Dùng JsonPath để tách lấy 1 hoặc nhiều value
  • Mapping json sang POJO để lấy nhiều value cùng lúc.

II. Cách mapping nói chung

JSONJava
stringString
numberint, long, double
booleanboolean
objectobject or Map<String, T>
arrayList
nullany object
Bảng mapping giữa json và java

Ví dụ:

Bạn sẽ cần các methods của JsonPath rest-assured để convert từ json sang POJO.

  • Get 1 object
public <T> T getObject(String path, Class<T> objectType)

VD:
.getObject("", StoreResponse.class);
  • Get List của 1 object nào đó
public <T> List<T> getList(String path, Class<T> genericType)

VD:
.getList("menu.popup.menuitem", MenuItem.class);
.getList("", Config.class);

III. Các trường hợp mapping

1. Json có cả object, array, string, number

{
    "store": {
        "book": [
            {
                "category": "reference",
                "author": "Nigel Rees",
                "title": "Sayings of the Century",
                "price": 5.95
            },
            {
                "category": "fiction",
                "author": "Evelyn Waugh",
                "title": "Sword of Honour",
                "price": 12.99
            },
            {
                "category": "fiction",
                "author": "Herman Melville",
                "title": "Moby Dick",
                "isbn": "0-553-21311-3",
                "price": 8.99
            },
            {
                "category": "fiction",
                "author": "J. R. R. Tolkien",
                "title": "The Lord of the Rings",
                "isbn": "0-395-19395-8",
                "price": 22.99
            }
        ],
        "bicycle": {
            "color": "red",
            "price": 19.95
        }
    }
}

POJO tương ứng:

@Data
public class StoreResponse {
    private Store store;

    @Data
    static class Store {
        private List<Book> book;
        private Bicycle bicycle;
    }

    @Data
    static class Book {
        private String category;
        private String author;
        private String title;
        private double price;
        private String isbn;
    }

    @Data
    static class Bicycle {
        private String color;
        private double price;
    }
}

Bạn hoàn toàn có thể dùng static class để không phải tạo mỗi 1 class ở 1 file riêng.

Code mẫu:

Response res = ... //call api
StoreResponse storeRes = res.jsonPath().getObject("", StoreResponse.class);

Từ object StoreResponse, bạn có thể lấy mọi thứ trong json.

  • Lấy toàn bộ title các cuốn sách.
List<String> titles = storeRes.getStore().getBook()
        .stream()
        .map(StoreResponse.Book::getTitle)
        .collect(Collectors.toList());
System.out.println(titles);
//[Sayings of the Century, Sword of Honour, Moby Dick, The Lord of the Rings]
  • Lấy price của bicycle:
double price = storeRes.getStore().getBicycle().getPrice();
System.out.println(price);
//19.95

2. Bạn chỉ muốn lấy 1 vài fileds vì object đó quá nhiều fields.

Ví dụ:

[
  {
    "description": "h",
    "direction": 3,
    "id": "W4ECoXQBUKCmoPq7wNg0",
    "ip": "4.6.7.8",
    "port": 0,
    "protocol": 500,
    "time_created": 1600429495
  },
  {
    "description": "import from file",
    "direction": 3,
    "id": "w0eBfHEB9R5R0nHL3f61",
    "ip": "1.1.1.80",
    "port": 33,
    "protocol": 58,
    "time_created": 1586931817
  },
  {
    "description": "import from file",
    "direction": 1,
    "id": "u0eBfHEB9R5R0nHL3P6h",
    "ip": "1.1.1.70",
    "port": 33,
    "protocol": 6,
    "time_created": 1586931817
  }
]

Mình chỉ muốn lấy 2 thông tin là ipport, mình ko nhất thiết phải làm POJO mapping vào từng field của json, bạn có thể dùng annotation của Jackson.

@JsonIgnoreProperties(ignoreUnknown=true)

POJO tương ứng:

@Data
@JsonIgnoreProperties(ignoreUnknown=true)
public class Config {
    private String ip;
    private int port;
}

Code mẫu:

List<Config> configs = JsonPath.with(res).getList("", Config.class);
configs.forEach(System.out::println);
//Config(ip=4.6.7.8, port=0)
//Config(ip=1.1.1.80, port=33)
//Config(ip=1.1.1.70, port=33)

3. Bạn chỉ muốn lấy 1 object con bên trong 1 object to.

Json ban đầu, mình chỉ muốn lấy phần menuitem

{
  "menu": {
    "id": "file",
    "value": "File",
    "popup": {
      "menuitem": [
        {
          "value": "New",
          "onclick": "CreateNewDoc()"
        },
        {
          "value": "Open",
          "onclick": "OpenDoc()"
        },
        {
          "value": "Close",
          "onclick": "CloseDoc()"
        }
      ]
    }
  }
}

POJO

@Data
public class MenuItem {
    private String value;
    private String onclick;
}

Code mẫu:

List<MenuItem> items = JsonPath.with(res).getList("menu.popup.menuitem", MenuItem.class);
items.forEach(System.out::println);
//MenuItem(value=New, onclick=CreateNewDoc())
//MenuItem(value=Open, onclick=OpenDoc())
//MenuItem(value=Close, onclick=CloseDoc())

IV. Tổng kết

Trong bài, mình đã giới thiệu tổng hợp 1 số các kiến thức và các trường hợp khi mapping từ json sang POJO. Hi vọng có ích cho các bạn đang làm api testing có sử dụng rest-assured.

5 1 vote
Article Rating
Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments