使用Dropwizard框架构建API,我使用Jackson ObjectMapper遇到了这个反序列化问题。我同时使用Joda Time和Joda Money。对于JodaTime,定义JodaModule足以解决反序列化问题。但对于JodaMoney来说,JodaModule不足以解决反序列化问题(如果我错了,请纠正我)。因此,我为JodaTime保留了JodaModule,创建了JodaMoney特定的反序列化程序。
public class JodaMoneyDeserializer extends JsonDeserializer<Money> {
@Override
public Money deserialize(JsonParser parser, DeserializationContext context) throws IOException, JsonProcessingException {
String text = parser.getText();
return Money.parse(text);
}
}
对于产品模型,我为Money添加了反序列化器。如果我需要定义其他内容,请告诉我。
public class Product {
...
private Money price;
...
...
@JsonDeserialize(using=JodaMoneyDeserializer.class)
public void setPrice(Money price) {
this.price = price;
}
...
}
这将尝试仅解析“{”,并将引发错误。
非常感谢任何提示。
如果您需要其他信息,请告诉我。
谢谢
**更新**以下是JSON示例。
{
"id": 15,
"productTypeId": 1,
"code": "XYZK",
"name": "PRODUCT - XYZK",
"status": true,
"visible": true,
"createdAt": 1400572157000,
"updatedAt": 1398995061000,
"description": "description of product",
"designator": "XYZK",
"number": "9.032",
"ingredients": "ingredient 1, ingredient 2, ingredient 3",
"size": null,
"weight": 0,
"googleProductCategory": "Health > Personal Care > Color",
"metaDescription": null,
"metaKeyword": null,
"metaTitle": null,
"price": {
"scale": 2,
"amount": 19.95,
"positive": true,
"positiveOrZero": true,
"negativeOrZero": false,
"amountMajor": 34,
"amountMajorLong": 34,
"amountMajorInt": 34,
"amountMinor": 3495,
"amountMinorLong": 3495,
"amountMinorInt": 3495,
"minorPart": 95,
"currencyUnit": {
"code": "USD",
"numericCode": 840,
"decimalPlaces": 2,
"numeric3Code": "840",
"countryCodes": [
"AS",
"US",
"EC",
"MP",
"TL",
"VI",
"VG",
"GU",
"SV",
"MH",
"PW",
"PR",
"FM",
"TC"
],
"pseudoCurrency": false,
"symbol": "$",
"currencyCode": "USD",
"defaultFractionDigits": 2
},
"zero": false,
"negative": false
},
"subPrice": {
"scale": 2,
"amount": 0,
"positive": false,
"positiveOrZero": true,
"negativeOrZero": true,
"amountMajor": 0,
"amountMajorLong": 0,
"amountMajorInt": 0,
"amountMinor": 0,
"amountMinorLong": 0,
"amountMinorInt": 0,
"minorPart": 0,
"currencyUnit": {
"code": "USD",
"numericCode": 840,
"decimalPlaces": 2,
"numeric3Code": "840",
"countryCodes": [
"AS",
"US",
"EC",
"MP",
"TL",
"VI",
"VG",
"GU",
"SV",
"MH",
"PW",
"PR",
"FM",
"TC"
],
"pseudoCurrency": false,
"symbol": "$",
"currencyCode": "USD",
"defaultFractionDigits": 2
},
"zero": true,
"negative": false
},
"priceGroupId": 1,
"ignoreFulfillment": false,
"upc": "2394823409820",
"productSKU": "XYZK",
"boxSKUInitial": "12345",
"boxSKURefill": "12345",
"urlKey": "capri-blonde",
"isAddon": false,
"extendedInfoJson": null
}
我得到的例外。
com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token
...
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:749)
at com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:55)
at com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:12)
at com.fasterxml.jackson.databind.ObjectMapper._readValue(ObjectMapper.java:3025)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:1637)
at com.fasterxml.jackson.core.JsonParser.readValueAs(JsonParser.java:1346)
at com.madisonreed.monocle.dao.mapper.deserializer.MoneyDeserializer.deserialize(MoneyDeserializer.java:26)
at com.madisonreed.monocle.dao.mapper.deserializer.MoneyDeserializer.deserialize(MoneyDeserializer.java:18)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:538)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:332)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1058)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:268)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:124)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3053)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2148)
at com.madisonreed.monocle.resources.ProductResourceTest.testGetProduct(ProductResourceTest.java:127)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30)
at io.dropwizard.testing.junit.DropwizardAppRule$1.evaluate(DropwizardAppRule.java:55)
at org.junit.rules.RunRules.evaluate(RunRules.java:18)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:53)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:123)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:104)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:164)
at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:110)
at org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:175)
at org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcessWhenForked(SurefireStarter.java:107)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:68)
这就是我注册反序列化程序的方式。
SimpleModule module = new SimpleModule();
module.addDeserializer(Money.class, new MoneyDeserializer());
mapper = new ObjectMapper();
mapper.registerModule(module);
mapper.registerModule(new JodaModule());
这是我反序列化产品对象的地方。
public void testGetProduct() {
System.out.println("getProduct");
ClientResponse response = client.resource(String.format("http://localhost:%d/api/v1/products/15", RULE.getLocalPort())).get(ClientResponse.class);
Product product = null;
Boolean validJson = false;
if (response.getStatus() == 200) {
String productJSON = response.getEntity(String.class);
validJson = JacksonJsonUtility.isValidJSON(productJSON);
System.out.println(productJSON);
try {
product = mapper.readValue(productJSON, Product.class);
} catch (IOException ex) {
ex.printStackTrace();
Logger.getLogger(ProductResourceTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
assertTrue(validJson);
}
您可以使用此MoneyDeserializer,然后注册此反序列化程序
public class MoneyDeserializer extends JsonDeserializer<Money> {
@Override
public Money deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
String currencyCode = "GBP";
ObjectMapper mapper = (ObjectMapper) jp.getCodec();
ObjectNode root = mapper.readTree(jp);
DoubleNode amountNode = (DoubleNode) root.findValue("amount");
String amount = null;
if (null != amountNode) {
amount = amountNode.asText();
}
JsonNode currencyUnitNode = root.get("currencyUnit");
JsonNode currencyCodeNode = currencyUnitNode.get("currencyCode");
currencyCode = currencyCodeNode.textValue();
if (StringUtils.isBlank(amount) || StringUtils.isBlank(currencyCode)) {
throw new IOException("unable to parse json");
}
return Money.parse(currencyCode + " " + amount);
}}
然后注册反序列化程序:
ObjectMapper mapper = new ObjectMapper();
JodaModule module = new JodaModule();
module.addDeserializer(Money.class, new MoneyDeserializer());
mapper.registerModule(module);
YourClass yourclass= mapper.readValue(jsonString, YourClass.class);
下面是为 Joda Money 类型注册序列化程序和反序列化程序的示例。所有 Money 对象都将转换为 JSON 字符串。
public class JacksonJodaMoney {
public static class Product {
public final Money price;
@JsonCreator
public Product(@JsonProperty("price") Money price) {
this.price = price;
}
@Override
public String toString() {
return "Product{" +
"price=" + price +
'}';
}
}
private static class MoneySerializer extends StdSerializer<Money> {
protected MoneySerializer() {
super(Money.class);
}
@Override
public void serialize(Money value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
jgen.writeString(value.toString());
}
}
private static class MoneyDeserializer extends StdDeserializer<Money> {
protected MoneyDeserializer() {
super(Money.class);
}
@Override
public Money deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
return Money.parse(jp.readValueAs(String.class));
}
}
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
Product value = new Product(Money.of(CurrencyUnit.EUR, 40.55));
SimpleModule module = new SimpleModule();
module.addDeserializer(Money.class, new MoneyDeserializer());
module.addSerializer(Money.class, new MoneySerializer());
mapper.registerModule(module);
String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(value);
System.out.println(json);
System.out.println(mapper.readValue(json, Product.class));
}
}
输出:
{
"price" : "EUR 40.55"
}
Product{price=EUR 40.55}
问题内容: 我需要执行RestRequest并获取一些JSON,因此我不确定我的方法是否真正异步,因为使用此方法时,UI仍然有些冻结。 特别针对以下代码行: 真的不同步吗?因为它似乎阻塞了UI。您能告诉我如何使此函数正确异步吗? 问题答案: 似乎作为参数传递给的委托正在UI线程上执行。如果是这种情况,只需使用即可在线程池上运行委托。 是田野吗?在我看来,它应该是局部变量。另外,在反序列化json之
我有一个问题,将时间值反序列化为本地时间-授予,我对Nodatime很陌生。我想导入一个web服务结果,它以“hh:mm”格式列出了一个时间。除非使用“hh:mm:ss.fff”格式的时间,否则会出现异常。是否有一种方法可以指定一个不同的模式并让“hh:mm”工作? 请看此代码 引发异常:
问题内容: 我是C ++的新手。使用序列化和反序列化类型数据的最简单方法是什么。我发现了一些使用示例,但它们对我来说是晦涩的。 问题答案: 请注意,将键解释为路径,例如,将对“ ab” =“ z”放置将创建{“ a”:{“ b”:“ z”}} JSON,而不是{“ ab”:“ z”} 。否则,使用是微不足道的。这是一个小例子。
我正在开发一个应用程序,它使用Gson作为JSON反序列化器,需要从REST API反序列化多态JSON。在解释mi问题之前,请注意,我已经用Gson研究了多态反序列化,并在几个案例中成功地实现了它。这是我面临的一个具体问题。在问这个问题之前,我也读过这篇很棒的帖子和关于堆栈溢出的讨论。顺便说一下,我正在使用RuntimeTypeAdapterFactory来反序列化多态对象。 我遇到的问题是,G
我使用的是带有Kafka活页夹和Avro的SpringCloudStream版本2.2.0。显然,一个不正确的记录被发布到Kafka主题中,导致所有消费者返回反序列化错误,并进行某种无限重试。 从技术上讲,应该有一种方法可以指定反序列化异常的策略。我可以找到一些不同的策略,如和,但它们适用于我在应用程序中不使用的Kafka流。如果有人能帮助我理解这里缺少什么,我将不胜感激。
问题内容: 我在反序列化以下json数组时遇到麻烦(对不起,大小): 如果将其粘贴到json-viewer中,则会得到以下结构: 现在,包含具有坐标的数组的数组具有可变大小。所以我想在Java中,整个对象应该是一个数组,其中包含数组的集合,每个数组都包含一个。就像是 但是gson不接受这一点。我收到以下错误消息: 这似乎很奇怪,因为对我来说好像不像一个数组。但这可能使我感到困惑,或多或少地迷路了…