json解析对象时指定解析
将面向对象的后端与外部系统集成的传统方式是通过数据传输对象 ,这些对象在外出之前先序列化为JSON,然后在返回时反序列化。 这种方法很流行,而且是错误的。 序列化部分应该由打印机代替,我在前面已经解释过。 这是我对反序列化的看法,应该通过猜测对象来完成。
假设有一个后端入口点,应该在库中注册一本新书,并以JSON格式到达:
{
"title": "Object Thinking",
"isbn: "0735619654",
"author: "David West"
}
另外,还有一个类Library
的对象,它希望将Book
类型的对象赋予其方法register()
:
class Library {
public void register(Book book) {
// Create a new record in the database
}
}
还可以说,类型Book
有一个简单的方法isbn()
:
interface Book {
String isbn();
}
现在,这是HTTP入口点(我正在使用Takes和Cactoos ),该入口点接受POST multipart/form-data
请求并将书注册到库中:
public class TkUpload implements Take {
private final Library library;
@Override
public Response act(Request req) {
String body = new RqPrint(
new RqMtSmart(new RqMtBase(req)).single("book")
).printBody();
JsonObject json = Json.createReader(
new InputStreamOf(body)
).readObject();
Book book = new BookDTO();
book.setIsbn(json.getString("isbn"));
library.register(book);
}
}
这有什么问题? 好吧,几件事。
首先,它不可重用。 如果在其他地方需要类似的东西,我们将不得不再次编写此HTTP处理和JSON解析。
其次,错误处理和验证也不可重复使用。 如果将其添加到上述方法中,则必须将其复制到各处。 当然,DTO可以封装它,但这不是DTO通常的用途。
第三,以上代码具有相当的程序性,并且具有大量的时间耦合 。
更好的设计是将此解析隐藏在新类JsonBook
:
class JsonBook implements Book {
private final String json;
JsonBook(String body) {
this.json = body;
}
@Override
public String isbn() {
return Json.createReader(
new InputStreamOf(body)
).readObject().getString("isbn");
}
}
然后,RESTful入口点将如下所示:
public class TkUpload implements Take {
private final Library library;
@Override
public Response act(Request req) {
library.register(
new JsonBook(
new RqPrint(
new RqMtSmart(new RqMtBase(req)).single("book")
).printBody()
)
);
}
}
那不是更优雅吗?
下面是一些例子,从我的项目: RqUser
从zerocracy /农场和RqUser
从yegor256 / jare 。
从上面的示例中可以看到,有时我们不能使用implements
因为Java中的某些原语不是接口而是final
类: String
是一个“完美”的示例。 这就是为什么我必须这样做:
class RqUser implements Scalar<String> {
@Override
public String value() {
// Parsing happens here and returns String
}
}
但是除此之外,这些示例还完美地说明了上面建议的“解析对象”的原理。
翻译自: https://www.javacodegeeks.com/2018/03/dont-parse-use-parsing-objects.html
json解析对象时指定解析