Các nhà phát triển Java thường ghen tị với JavaScript vì nó dễ dàng phân tích cú pháp JSON. Mặc dù Java mang lại sự mạnh mẽ hơn, nhưng nó có xu hướng liên quan đến nhiều công việc hơn và mã soạn sẵn. Nhờ dự án Manifold, giờ đây Java có khả năng vượt trội hơn JavaScript trong việc phân tích cú pháp và xử lý các tệp JSON.
Manifold là một tập hợp các phần mở rộng ngôn ngữ mang tính cách mạng dành cho Java, thay đổi hoàn toàn cách chúng ta xử lý JSON (và hơn thế nữa…).
Mã cho hướng dẫn này có thể được tìm thấy trên trang GitHub của tôi. Manifold tương đối trẻ nhưng đã có nhiều khả năng. Bạn có thể tìm hiểu thêm về dự án trên trang web và kênh Slack của họ.
Để bắt đầu, bạn sẽ cần cài đặt plugin Manifold, hiện chỉ khả dụng cho JetBrains IDE. Dự án hỗ trợ các bản phát hành LTS của Java, bao gồm cả JDK 19 mới nhất.
Chúng tôi có thể cài đặt plugin từ giao diện người dùng cài đặt IntelliJ/IDEAs bằng cách điều hướng đến thị trường và tìm kiếm Manifold. Plugin đảm bảo IDE không xung đột với công việc được thực hiện bởi plugin Maven/Gradle.
Manifold bao gồm nhiều dự án nhỏ hơn, mỗi dự án cung cấp một phần mở rộng ngôn ngữ tùy chỉnh. Hôm nay, chúng ta sẽ thảo luận về một tiện ích mở rộng như vậy, nhưng còn nhiều điều nữa để khám phá.
Để minh họa Manifold, chúng tôi sẽ sử dụng một dự án Maven đơn giản (nó cũng hoạt động với Gradle). Trước tiên, chúng tôi cần dán phiên bản Manifold hiện tại từ trang web của họ và thêm các phụ thuộc cần thiết. Phần phụ thuộc chính của JSON là phần phụ thuộc manifold-json-rt
.
Các phần phụ thuộc khác có thể được thêm vào để hỗ trợ YAML, XML và CSV. Chúng ta cần thêm phần này vào tệp pom.xml
trong dự án.
Tôi biết một điều trớ trêu là việc giảm bớt bản soạn sẵn cho JSON bắt đầu với rất nhiều cấu hình trong tập lệnh xây dựng Maven. Nhưng đây là cấu hình, không phải "mã thực tế"; nó chủ yếu là sao chép và dán.
Lưu ý rằng nếu bạn muốn giảm mã này, thì mã tương đương Gradle sẽ ngắn gọn hơn khi so sánh.
Dòng này cần đi vào phần thuộc tính:
<manifold.version>2023.1.5</manifold.version>
Các phụ thuộc chúng tôi sử dụng là:
<dependencies> <dependency> <groupId>systems.manifold</groupId> <artifactId>manifold-json-rt</artifactId> <version>${manifold.version}</version> </dependency>
Plugin biên dịch là bản soạn sẵn kết hợp Manifold vào mã byte và làm cho nó trở nên liền mạch đối với chúng tôi. Đây là phần cuối cùng của thiết lập pom:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> <configuration> <source>19</source> <target>19</target> <encoding>UTF-8</encoding> <compilerArgs> <!-- Configure manifold plugin--> <arg>-Xplugin:Manifold</arg> </compilerArgs> <!-- Add the processor path for the plugin --> <annotationProcessorPaths> <path> <groupId>systems.manifold</groupId> <artifactId>manifold-json</artifactId> <version>${manifold.version}</version> </path> </annotationProcessorPaths> </configuration> </plugin> </plugins> </build>
Khi thiết lập hoàn tất, hãy đi sâu vào mã.
Chúng tôi đặt một tệp JSON mẫu trong thư mục dự án trong hệ thống phân cấp tài nguyên. Tôi đã đặt tệp này dưới src/main/resources/com/debugagent/json/Test.json
:
{ "firstName": "Shai", "surname": "Almog", "website": "https://debugagent.com/", "active": true, "details":[ {"key": "value"} ] }
Trong lớp chính, chúng tôi làm mới dự án Maven và bạn sẽ thấy một lớp Kiểm tra mới xuất hiện. Lớp này được Manifold tạo động dựa trên tệp JSON. Nếu bạn thay đổi JSON và làm mới Maven, mọi thứ sẽ cập nhật liền mạch.
Điều quan trọng là phải hiểu rằng Manifold không phải là trình tạo mã. Nó biên dịch JSON mà chúng ta vừa viết thành mã byte.
Lớp Kiểm tra đi kèm với một số khả năng tích hợp sẵn, chẳng hạn như API trình tạo an toàn kiểu cho phép bạn xây dựng các đối tượng JSON bằng các phương thức của trình tạo. Bạn cũng có thể tạo các đối tượng lồng nhau và chuyển đổi JSON thành một chuỗi bằng cách sử dụng các phương thức write()
và toJson()
.
Nó có nghĩa là bây giờ chúng ta có thể viết:
Test test = Test.builder().withFirstName("Someone") .withSurname("Surname") .withActive(true) .withDetails(List.of( Test.details.detailsItem.builder(). withKey("Value 1").build() )) .build();
Cái nào sẽ in ra JSON sau đây:
{ "firstName": "Someone", "surname": "Surname", "active": true, "details": [ { "key": "Value 1" } ] }
Tương tự, chúng ta có thể đọc một tệp JSON bằng cách sử dụng mã như sau:
Test readObject = Test.load().fromJson(""" { "firstName": "Someone", "surname": "Surname", "active": true, "details": [ { "key": "Value 1" } ] } """);
Lưu ý việc sử dụng cú pháp TextBlock
của Java 15 để viết một chuỗi dài. Phương thức load()
trả về một đối tượng bao gồm các API khác nhau để đọc JSON. Trong trường hợp này, nó được đọc từ String
nhưng có các API để đọc nó từ URL, tệp, v.v.
Manifold hỗ trợ nhiều định dạng khác nhau, bao gồm CSV, XML và YAML, cho phép bạn tạo và phân tích cú pháp bất kỳ định dạng nào trong số này mà không cần viết bất kỳ mã soạn sẵn nào hoặc hy sinh tính an toàn của loại. Để thêm hỗ trợ đó, chúng tôi sẽ cần thêm các phụ thuộc bổ sung vào tệp pom.xml:
<dependency> <groupId>systems.manifold</groupId> <artifactId>manifold-csv-rt</artifactId> <version>${manifold.version}</version> </dependency> <dependency> <groupId>systems.manifold</groupId> <artifactId>manifold-xml-rt</artifactId> <version>${manifold.version}</version> </dependency> <dependency> <groupId>systems.manifold</groupId> <artifactId>manifold-yaml-rt</artifactId> <version>${manifold.version}</version> </dependency> </dependencies>
Với các phụ thuộc bổ sung này, mã này sẽ in ra cùng một dữ liệu như tệp JSON... Với test.write().toCsv()
đầu ra sẽ là:
"firstName","surname","active","details" "Someone","Surname","true","[manifold.json.rt.api.DataBindings@71070b9c]"
Lưu ý rằng đầu ra Giá trị được phân tách bằng dấu phẩy (CSV) không bao gồm thông tin phân cấp. Đó là giới hạn của định dạng CSV chứ không phải lỗi của Manifold.
Với test.write().toXml()
đầu ra quen thuộc và ngắn gọn đến kinh ngạc:
<root_object firstName="Someone" surname="Surname" active="true"> <details key="Value 1"/> </root_object>
Với test.write().toYaml()
chúng ta lại nhận được một bản in quen thuộc:
firstName: Someone surname: Surname active: true details: - key: Value 1
Manifold cũng hoạt động trơn tru với lược đồ JSON, cho phép bạn thực thi các quy tắc và ràng buộc nghiêm ngặt. Điều này đặc biệt hữu ích khi làm việc với ngày và liệt kê.
Manifold tạo/cập nhật liền mạch mã byte tuân thủ lược đồ, giúp làm việc với dữ liệu JSON phức tạp dễ dàng hơn nhiều.
Lược đồ này được sao chép và dán từ dự án Manifold GitHub :
{ "$schema": "http://json-schema.org/draft-07/schema#", "$id": "http://example.com/schemas/User.json", "type": "object", "definitions": { "Gender": { "type": "string", "enum": ["male", "female"] } }, "properties": { "name": { "type": "string", "description": "User's full name.", "maxLength": 80 }, "email": { "description": "User's email.", "type": "string", "format": "email" }, "date_of_birth": { "type": "string", "description": "Date of uses birth in the one and only date standard: ISO 8601.", "format": "date" }, "gender": { "$ref" : "#/definitions/Gender" } }, "required": ["name", "email"] }
Đó là một lược đồ tương đối đơn giản, nhưng tôi muốn bạn chú ý đến một vài điều ở đây. Nó xác định tên và email theo yêu cầu. Đây là lý do tại sao khi chúng ta cố gắng tạo một đối tượng User
bằng cách sử dụng trình tạo trong Manifold, phương thức build()
yêu cầu cả hai tham số:
User.builder("Name", "[email protected]")
Đó mới chỉ là bắt đầu... Lược đồ bao gồm một ngày. Ngày tháng là một viễn cảnh khó khăn trong JSON, việc tiêu chuẩn hóa kém và có nhiều vấn đề. Lược đồ cũng bao gồm một trường giới tính thực sự là một enum.
Tất cả điều này được chuyển đổi thành ngữ nghĩa an toàn kiểu sử dụng các lớp Java phổ biến như LocalDate:
User u = User.builder("Name", "[email protected]") .withDate_of_birth(LocalDate.of(1999, 10, 11)) .withGender(User.Gender.male) .build();
Điều đó thậm chí có thể được thực hiện ngắn hơn với nhập tĩnh, nhưng ý chính của ý tưởng là rõ ràng. JSON thực sự có nguồn gốc từ Java trong Manifold.
Manifold là một dự án mạnh mẽ và thú vị. Nó cách mạng hóa việc phân tích cú pháp JSON trong Java, nhưng đó chỉ là một phần rất nhỏ trong những gì nó có thể làm!
Chúng tôi chỉ vạch ra bề nổi về khả năng của nó trong bài đăng này. Trong bài viết tiếp theo, chúng ta sẽ tìm hiểu sâu hơn về Manifold và khám phá một số tính năng bổ sung không mong muốn.
Vui lòng chia sẻ kinh nghiệm và suy nghĩ của bạn về Manifold trong phần bình luận. Nếu bạn có bất kỳ câu hỏi nào, đừng ngần ngại hỏi.