MonetaryAmount JSR354 / moneta 的自定义 Json 序列化格式,如何正确注册序列化程序
Custom Json serialization format for MonetaryAmount JSR354 / moneta, How to register the Serializer properly
你好 Whosebug 专家
我有以下 InvoiceItem Class,其中包含金额
import jakarta.json.bind.annotation.JsonbProperty;
import jakarta.json.bind.annotation.JsonbTypeSerializer;
import jakarta.json.bind.serializer.JsonbSerializer;
import jakarta.json.bind.serializer.SerializationContext;
import jakarta.json.stream.JsonGenerator;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import org.eclipse.persistence.annotations.UuidGenerator;
import org.javamoney.moneta.FastMoney;
@Entity
@UuidGenerator(name = "INVOICE_ITEM_GEN")
@Table(name = "invoice_items")
public class InvoiceItem {
@Getter
@Setter
@jakarta.persistence.Id
@JsonbProperty("id")
@GeneratedValue(generator = "INVOICE_ITEM_GEN")
private String Id;
@Getter
@Setter
@Column(name = "name")
@JsonbProperty("name")
private String Name;
@Getter
@Setter
@Convert(converter = PersistentFastMoney.class)
@Column(name = "price")
@JsonbProperty("price")
private FastMoney Price;
public InvoiceItem() {
}
public InvoiceItem(String name, String price) {
this.setName(name);
this.setPrice(FastMoney.parse(price));
}
}
我从不同的输入在我的函数中成功生成了这个。
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
@Path("/invoices")
public class InvoiceSystem {
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Invoice CreateNewInvoice(InvoiceInput input) {
var invoice = new Invoice();
invoice.setCreditor(new InvoiceParty());
for (var item: input.getItems()) {
invoice.Items.add(item.toInvoiceItem());
}
return invoice;
}
}
toInvoiceItem 使用带有两个字符串参数的 InvoiceItem 的构造函数。
现在我想在创建后将 Class 作为 JSON 打印回消费者。
但这失败了
<body><h1>HTTP Status 500 - Internal Server Error</h1>
<hr/>
<p><b>type</b> Exception report</p>
<p><b>message</b>Internal Server Error</p>
<p><b>description</b>The server encountered an internal error that prevented it from fulfilling this request.</p>
<p><b>exception</b>
<pre>javax.servlet.ServletException: javax.json.bind.JsonbException: Unable to serialize property 'Items' from com.openflowlabs.faktura.Invoice</pre>
</p><p><b>root cause</b>
<pre>javax.json.bind.JsonbException: Unable to serialize property 'Items' from com.openflowlabs.faktura.Invoice</pre>
</p><p><b>root cause</b>
<pre>javax.json.bind.JsonbException: Unable to serialize property 'price' from com.openflowlabs.faktura.InvoiceItem</pre>
</p><p><b>root cause</b>
<pre>javax.json.bind.JsonbException: Unable to serialize property 'context' from org.javamoney.moneta.FastMoney</pre>
</p><p><b>root cause</b>
<pre>javax.json.bind.JsonbException: Unable to serialize property 'amountType' from javax.money.MonetaryContext</pre>
</p><p><b>root cause</b>
<pre>javax.json.bind.JsonbException: Unable to serialize property 'annotatedInterfaces' from java.lang.Class</pre>
</p><p><b>root cause</b>
<pre>javax.json.bind.JsonbException: Unable to serialize property 'annotatedOwnerType' from sun.reflect.annotation.AnnotatedTypeFactory.AnnotatedTypeBaseImpl</pre>
</p><p><b>root cause</b>
<pre>javax.json.bind.JsonbException: Error getting value on: javax.money.MonetaryAmount</pre>
</p><p><b>root cause</b>
<pre>java.lang.IllegalAccessException: class org.eclipse.yasson.internal.model.ReflectionPropagation cannot access class sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedTypeBaseImpl (in module java.base) because module java.base does not export sun.reflect.annotation to unnamed module @50c1e8e3</pre>
</p><p><b>note</b> <u>The full stack traces of the exception and its root causes are available in the Payara Server
5.2022.1 #badassfish logs.</u></p>
<hr/>
<h3>Payara Server 5.2022.1 #badassfish</h3></body>
我知道我需要一个自定义序列化程序,但我尝试了一天所有可能的方法来制作一个,但我的应用程序根本不会吃注释
如何为 org.javamoney.moneta.FastMoney
Class 创建自定义序列化程序,以便我可以简单地用 @JsonbTypeSerializer(FastMoneySerializer.class)
注释所有具有此 class 的字段,例如发票项目
@Getter
@Setter
@Convert(converter = PersistentFastMoney.class)
@Column(name = "price")
@JsonbProperty("price")
@JsonbTypeSerializer(FastMoneySerializer.class)
private FastMoney Price;
这有可能吗?是否有一些关于我需要如何制作序列化程序的文档,所以它 returns JSON 像这样?
{
"name": "Testing",
"price": "CHF 20"
}
感谢您提供任何指示和/或解决方案,我真的被困住了,找不到关于如何使这些序列化程序工作的教程。如果您有一个带有良好文档的图书馆,那也会有所帮助。
好的,我找到了解决方案。
如果您想使用 jakarta.json,您的运行时需要支持它。我正在使用 Pyara,它说它支持 Jakarta EE9,但不知何故它不支持。切换到 GlassFish 解决了这个问题。正确的序列化器是这样完成的
package org.mypackage;
import jakarta.json.bind.serializer.JsonbSerializer;
import jakarta.json.bind.serializer.SerializationContext;
import jakarta.json.stream.JsonGenerator;
import org.javamoney.moneta.FastMoney;
public class FastMoneySerializer implements JsonbSerializer<FastMoney> {
@Override
public void serialize(FastMoney obj, JsonGenerator generator, SerializationContext ctx) {
var str = obj.toString();
generator.write(str);
}
}
然后您可以将其添加到具有 FastMoney 类型的 属性,如下所示:
package com.openflowlabs.faktura;
import jakarta.json.bind.annotation.JsonbAnnotation;
import jakarta.json.bind.annotation.JsonbProperty;
import jakarta.json.bind.annotation.JsonbTypeSerializer;
import jakarta.json.bind.serializer.JsonbSerializer;
import jakarta.json.bind.serializer.SerializationContext;
import jakarta.json.stream.JsonGenerator;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import org.eclipse.persistence.annotations.UuidGenerator;
import org.javamoney.moneta.FastMoney;
@Entity
@UuidGenerator(name = "INVOICE_ITEM_GEN")
@Table(name = "invoice_items")
public class InvoiceItem {
@Getter
@Setter
@jakarta.persistence.Id
@JsonbProperty("id")
@GeneratedValue(generator = "INVOICE_ITEM_GEN")
private String Id;
@Getter
@Setter
@Column(name = "name")
@JsonbProperty("name")
private String Name;
@Getter
@Setter
@Convert(converter = PersistentFastMoney.class)
@Column(name = "price")
@JsonbProperty("price")
@JsonbTypeSerializer(FastMoneySerializer.class)
private FastMoney Price;
public InvoiceItem() {
}
public InvoiceItem(String name, String price) {
this.setName(name);
this.setPrice(FastMoney.parse(price));
}
}
你好 Whosebug 专家
我有以下 InvoiceItem Class,其中包含金额
import jakarta.json.bind.annotation.JsonbProperty;
import jakarta.json.bind.annotation.JsonbTypeSerializer;
import jakarta.json.bind.serializer.JsonbSerializer;
import jakarta.json.bind.serializer.SerializationContext;
import jakarta.json.stream.JsonGenerator;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import org.eclipse.persistence.annotations.UuidGenerator;
import org.javamoney.moneta.FastMoney;
@Entity
@UuidGenerator(name = "INVOICE_ITEM_GEN")
@Table(name = "invoice_items")
public class InvoiceItem {
@Getter
@Setter
@jakarta.persistence.Id
@JsonbProperty("id")
@GeneratedValue(generator = "INVOICE_ITEM_GEN")
private String Id;
@Getter
@Setter
@Column(name = "name")
@JsonbProperty("name")
private String Name;
@Getter
@Setter
@Convert(converter = PersistentFastMoney.class)
@Column(name = "price")
@JsonbProperty("price")
private FastMoney Price;
public InvoiceItem() {
}
public InvoiceItem(String name, String price) {
this.setName(name);
this.setPrice(FastMoney.parse(price));
}
}
我从不同的输入在我的函数中成功生成了这个。
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
@Path("/invoices")
public class InvoiceSystem {
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Invoice CreateNewInvoice(InvoiceInput input) {
var invoice = new Invoice();
invoice.setCreditor(new InvoiceParty());
for (var item: input.getItems()) {
invoice.Items.add(item.toInvoiceItem());
}
return invoice;
}
}
toInvoiceItem 使用带有两个字符串参数的 InvoiceItem 的构造函数。 现在我想在创建后将 Class 作为 JSON 打印回消费者。
但这失败了
<body><h1>HTTP Status 500 - Internal Server Error</h1>
<hr/>
<p><b>type</b> Exception report</p>
<p><b>message</b>Internal Server Error</p>
<p><b>description</b>The server encountered an internal error that prevented it from fulfilling this request.</p>
<p><b>exception</b>
<pre>javax.servlet.ServletException: javax.json.bind.JsonbException: Unable to serialize property 'Items' from com.openflowlabs.faktura.Invoice</pre>
</p><p><b>root cause</b>
<pre>javax.json.bind.JsonbException: Unable to serialize property 'Items' from com.openflowlabs.faktura.Invoice</pre>
</p><p><b>root cause</b>
<pre>javax.json.bind.JsonbException: Unable to serialize property 'price' from com.openflowlabs.faktura.InvoiceItem</pre>
</p><p><b>root cause</b>
<pre>javax.json.bind.JsonbException: Unable to serialize property 'context' from org.javamoney.moneta.FastMoney</pre>
</p><p><b>root cause</b>
<pre>javax.json.bind.JsonbException: Unable to serialize property 'amountType' from javax.money.MonetaryContext</pre>
</p><p><b>root cause</b>
<pre>javax.json.bind.JsonbException: Unable to serialize property 'annotatedInterfaces' from java.lang.Class</pre>
</p><p><b>root cause</b>
<pre>javax.json.bind.JsonbException: Unable to serialize property 'annotatedOwnerType' from sun.reflect.annotation.AnnotatedTypeFactory.AnnotatedTypeBaseImpl</pre>
</p><p><b>root cause</b>
<pre>javax.json.bind.JsonbException: Error getting value on: javax.money.MonetaryAmount</pre>
</p><p><b>root cause</b>
<pre>java.lang.IllegalAccessException: class org.eclipse.yasson.internal.model.ReflectionPropagation cannot access class sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedTypeBaseImpl (in module java.base) because module java.base does not export sun.reflect.annotation to unnamed module @50c1e8e3</pre>
</p><p><b>note</b> <u>The full stack traces of the exception and its root causes are available in the Payara Server
5.2022.1 #badassfish logs.</u></p>
<hr/>
<h3>Payara Server 5.2022.1 #badassfish</h3></body>
我知道我需要一个自定义序列化程序,但我尝试了一天所有可能的方法来制作一个,但我的应用程序根本不会吃注释
如何为 org.javamoney.moneta.FastMoney
Class 创建自定义序列化程序,以便我可以简单地用 @JsonbTypeSerializer(FastMoneySerializer.class)
注释所有具有此 class 的字段,例如发票项目
@Getter
@Setter
@Convert(converter = PersistentFastMoney.class)
@Column(name = "price")
@JsonbProperty("price")
@JsonbTypeSerializer(FastMoneySerializer.class)
private FastMoney Price;
这有可能吗?是否有一些关于我需要如何制作序列化程序的文档,所以它 returns JSON 像这样?
{
"name": "Testing",
"price": "CHF 20"
}
感谢您提供任何指示和/或解决方案,我真的被困住了,找不到关于如何使这些序列化程序工作的教程。如果您有一个带有良好文档的图书馆,那也会有所帮助。
好的,我找到了解决方案。
如果您想使用 jakarta.json,您的运行时需要支持它。我正在使用 Pyara,它说它支持 Jakarta EE9,但不知何故它不支持。切换到 GlassFish 解决了这个问题。正确的序列化器是这样完成的
package org.mypackage;
import jakarta.json.bind.serializer.JsonbSerializer;
import jakarta.json.bind.serializer.SerializationContext;
import jakarta.json.stream.JsonGenerator;
import org.javamoney.moneta.FastMoney;
public class FastMoneySerializer implements JsonbSerializer<FastMoney> {
@Override
public void serialize(FastMoney obj, JsonGenerator generator, SerializationContext ctx) {
var str = obj.toString();
generator.write(str);
}
}
然后您可以将其添加到具有 FastMoney 类型的 属性,如下所示:
package com.openflowlabs.faktura;
import jakarta.json.bind.annotation.JsonbAnnotation;
import jakarta.json.bind.annotation.JsonbProperty;
import jakarta.json.bind.annotation.JsonbTypeSerializer;
import jakarta.json.bind.serializer.JsonbSerializer;
import jakarta.json.bind.serializer.SerializationContext;
import jakarta.json.stream.JsonGenerator;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import org.eclipse.persistence.annotations.UuidGenerator;
import org.javamoney.moneta.FastMoney;
@Entity
@UuidGenerator(name = "INVOICE_ITEM_GEN")
@Table(name = "invoice_items")
public class InvoiceItem {
@Getter
@Setter
@jakarta.persistence.Id
@JsonbProperty("id")
@GeneratedValue(generator = "INVOICE_ITEM_GEN")
private String Id;
@Getter
@Setter
@Column(name = "name")
@JsonbProperty("name")
private String Name;
@Getter
@Setter
@Convert(converter = PersistentFastMoney.class)
@Column(name = "price")
@JsonbProperty("price")
@JsonbTypeSerializer(FastMoneySerializer.class)
private FastMoney Price;
public InvoiceItem() {
}
public InvoiceItem(String name, String price) {
this.setName(name);
this.setPrice(FastMoney.parse(price));
}
}