我正在尝试使用fasterxml将json回复解析为POJO。但问题是json回复包括嵌套的对象,这些对象包括反斜杠,所以在ObjectMapper读取该值的过程中,我收到了com.fasterxml.jackson.databind.exc.MismatchedInputException
com.fasterxml.jackson.databind.exc.MismatchedInputException:无法构造
com.am.api.Message
的实例(尽管至少存在一个创建者):没有要从字符串值反序列化的字符串参数构造函数/工厂方法('{"entryType":"Buy","rate":"22000.0","action":"update","offerId":"b96f2da7-5f9-4221-aaa3-8e3ad177567d","market":"BTC-PLN","state":"买入","id":"b96f2da7-5f9-4221-aaa3-8e3ad177567d","currentAmount":"0.0005","lockedAmount","11.00","rate":"220000"在[来源:(字符串)"{"主题":"交易/报价/BTC-PPLN","message":"{\"entryType\":\"Buy\",\"rate\":"22000.0\","action\":"update\",\"offerId":\"b96f2da7-5f9-4221-aaa3-8e3ad177567d",\"market\":\"BTC-PLN",\ \"currentAmount\":\"0.0005\",\"lockedAmount\":\"11.00\",\"rate":\"220000\",\"startAmount\\":false,\"hidden\":false、\"mode\":\"limit\"、\"receivedAmoun"[截断45个字符];行:3,列:13](通过引用链:com.am.api.WsOrderReply["message"])来自(MismatchedInputException.java:63)网址:com.fasterxml.jackson.databind.DDeserializationContext.reportInputMismatch(Deserialization Context.java:1329)网址:com.fasterxml.jackson.databind.DDeserializationContext.handleMissingInstantiator(Deserialization Context.java:1031)网址:com.fasterxml.jackson.databind.deser.ValueInstantiator_createFromStringFallbacks(ValueInstantiator.java:370)网址:com.fasterxml.jackson.databind.deser.StdValueInstantiator.createFromString(StdValueInstantiater.java:314)网址:com.fasterxml.jackson.databind.deser.BBeanSerializerBase.destrializeFromString(BeanSerializer Base.java:1351)网址:com.fasterxml.jackson.databind.deser.BeanSerializer._deserializeOther(BeanSerializer.java:170)网址:com.fasterxml.jackson.databind.deser.BeanSerializer.deserialize(BeanSerializer.java:161)网址:com.fasterxml.jackson.databind.deser.SetableBeanProperty.destrialize(SettableBeanProperty.java:519)网址:com.fasterxml.jackson.databind.deser.BeanSerializer._deserializeWithErrorWrapping(BeanSerializer.java:527)网址:com.fasterxml.jackson.databind.deser.BeanSerializer._deserializerUsingPropertyBased(BeanSerializer.java:416)网址:com.fasterxml.jackson.databind.deser.BBeanSerializerBase.destrializeFromObjectUsingNonDefault(BeanSerializer Base.java:1265)网址:com.fasterxml.jackson.databind.deser.BeanSerializer.deserializeFromObject(BeanSerializer.java:325)网址:com.fasterxml.jackson.databind.deser.BeanSerializer.deserialize(BeanSerializer.java:159)网址:com.fasterxml.jackson.databind.ObjectMapper.readMapAndClose(ObjectMapper.java:4001)网址:com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2992)网址:com.am.ReplyMapper.readValue(ReplyMapper.java:154)网址:com.am.ReplyMapper.mapReplyToCommonExecutionReport(ReplyMapper.java:73)网址:com.am.ReplyMapper.lambda$apply$1(ReplyMapper.java:54)位于java.util.Optional.map(Optional.java:215)网址:com.am.ReplyMapper.apply(ReplyMapper.java:54)网址:com.am.ReplyMapperTest.huldMapUpdateOrderReplyNew(ReplyMapperTest.java:64)在sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)位于sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)位于java.lang.reflect.Method.ioke(Method.java:498)网址:org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)网址:org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)位于org.junit.runners.model.FrameworkMethod.invokeExplorery(FrameworkMethod.java:47)位于org.junit.internal.runners.statements.InvokeMethod.eevaluate(InvokeMethod.java:17)网址:org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)网址:org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)网址:org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)网址:org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)网址:org.junit.runners.ParentRunner$1schedule(ParentRunner.java:71)网址:org.junit.runners.ParentRunner.runChildren(ParentRunnr.java:288)网址:org.junit.runners.ParentRunner.access$000(ParentRunner:58)网址:org.junit.runners.ParentRunner$2.eevaluate(ParentRunner.java:268)网址:org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)网址:org.junit.runners.ParentRunner.run(ParentRunner:363)网址:org.junit.runner.JUnitCore.run(JUnitCores.java:137)网址:com.intellij.junit4.JUnit4DeaTestRunner.startRunnerWithArgs(JUnit4DieTestRunner.java:68)网址:com.intellij.rt.execution.junit.IideaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)网址:com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)网址:com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
我不知道如何使用fasterxml解析这个对象?!
我的POJO对象模型如下:
@EqualsAndHashCode
@ToString
@Getter
@Builder
public class WsOrderReply {
private final String topic;
private final Message message;
private final Long timestamp;
@JsonCreator
public WsOrderReply(
@JsonProperty("topic") String topic,
@JsonProperty("message") Message message,
@JsonProperty("timestamp") Long timestamp) {
this.topic = topic;
this.message = message;
this.timestamp = timestamp;
}
}
@EqualsAndHashCode
@ToString
@Getter
public class Message {
private final String entryType;
private final BigDecimal rate;
private final String action;
private final String offerId;
private final String market;
private final State state;
@JsonCreator
public Message(
@JsonProperty("entryType") String entryType,
@JsonProperty("rate") BigDecimal rate,
@JsonProperty("action") String action,
@JsonProperty("offerId") String offerId,
@JsonProperty("market") String market,
@JsonProperty("state") State state) {
this.entryType = entryType;
this.rate = rate;
this.action = action;
this.offerId = offerId;
this.market = market;
this.state = state;
}
}
@EqualsAndHashCode
@ToString
@Getter
public class State {
private final String market;
private final String offerType;
private final String id;
private final BigDecimal currentAmount;
private final BigDecimal lockedAmount;
private final BigDecimal rate;
private final BigDecimal startAmount;
private final String time;
private final boolean postOnly;
private final boolean hidden;
private final String mode;
private final BigDecimal receivedAmount;
public State(
@JsonProperty("market") String market,
@JsonProperty("offerType") String offerType,
@JsonProperty("id") String id,
@JsonProperty("currentAmount") BigDecimal currentAmount,
@JsonProperty("lockedAmount") BigDecimal lockedAmount,
@JsonProperty("rate") BigDecimal rate,
@JsonProperty("startAmount") BigDecimal startAmount,
@JsonProperty("time") String time,
@JsonProperty("postOnly") boolean postOnly,
@JsonProperty("hidden") boolean hidden,
@JsonProperty("mode") String mode,
@JsonProperty("receivedAmount") BigDecimal receivedAmount) {
this.market = market;
this.offerType = offerType;
this.id = id;
this.currentAmount = currentAmount;
this.lockedAmount = lockedAmount;
this.rate = rate;
this.startAmount = startAmount;
this.time = time;
this.postOnly = postOnly;
this.hidden = hidden;
this.mode = mode;
this.receivedAmount = receivedAmount;
}
}
我收到的原始json消息:
{"主题":"交易/报价/BTC-PPLN","message":"{\"entryType\":\"Buy\",\"rate\":"22000.0\","action\":"update\",\"offerId":\"b96f2da7-5f9-4221-aaa3-8e3ad177567d",\"market\":\"BTC-PLN",\ \"currentAmount\":\"0.0005\",\"lockedAmount\":\"11.00\",\"rate":\"220000\",\"startAmount\\":false,\"hidden\":false、\"mode\":\"limit\"、\"receivedAmount\":"0\"}}","时间戳":1535023208264}
我的JUnit测试:
public class ReplyMapperTest {
private static ObjectMapper objectMapper;
private MessageFactory msgFactory = new quickfix.fix42.MessageFactory();
private TypeSelector fixMsgBuilder = FixMessageBuilder
.usingFactory(msgFactory::create)
.withBeginString(FixVersions.BEGINSTRING_FIX42);
private ReplyMapper replyMapper = new ReplyMapper(objectMapper, fixMsgBuilder);
@BeforeClass
public static void beforeClass() {
objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
@Test
public void shouldMapUpdateOrderReplyNew() throws FieldNotFound, IOException {
String json = IOUtils.toString(this.getClass().getResourceAsStream("/json/UpdateOrderReplyNew.json"), StandardCharsets.UTF_8);
//When
List<Message> result = replyMapper.apply(json);
//Then
assertThat(result.get(0).getHeader().getString(MsgType.FIELD), is(Heartbeat.MSGTYPE));
}
也许有人也和我有同样的问题。如何解决这个问题?
您使用的JSON是不正确的,即使在未跳过的情况下也是如此因此,它将整个对象视为一个字符串。使用正确的转义json将解决问题,我已经为您更正了json,现在看看它是否工作
{rnt"topic": "trading/offers/BTC-PLN",rnt"message": {rntt"entryType": "Buy",rntt"rate": "22000.0",rntt"action": "update",rntt"offerId": "b96f2da7-55f9-4221-aaa3-8e3ad177567d",rntt"market": "BTC-PLN",rntt"state": {rnttt"market": "BTC-PLN",rnttt"offerType": "Buy",rnttt"id": "b96f2da7-55f9-4221-aaa3-8e3ad177567d",rnttt"currentAmount": "0.0005",rnttt"lockedAmount": "11.00",rnttt"rate": "22000.0",rnttt"startAmount": "0.0005",rnttt"time": "1535023208260",rnttt"postOnly": false,rnttt"hidden": false,rnttt"mode": "limit",rnttt"receivedAmount": "0"rntt}rnt},rnt"timestamp": 1535023208264rn}
如果Json不能更改,那么您需要在构造函数中获得作为String值的消息,然后使用对象映射器将其显式转换为对象
public class WsOrderReply {
private final String topic;
private final Message message;
private final Long timestamp;
ObjectMapper mapper = new ObjectMapper();
@JsonCreator
public WsOrderReply(
@JsonProperty("topic") String topic,
@JsonProperty("message") String messageString,
@JsonProperty("timestamp") Long timestamp) {
this.topic = topic;
this.message = mapper.readValue(messageString, Message.class);;
this.timestamp = timestamp;
}
}
另一个不需要更改模型类就能工作的解决方案是从服务器获取JSON,然后在本地将其更改为第一种方法中提到的格式