I have a sqs queue , I am polling for messages .
I get the message in following format
{
"Type" : "type_value",
"MessageId" : "message_id",
"TopicArn" : "topic_arn",
"Message" : "{\n \"contentType\": \"content_type_value\",\n \"content\": \"content_value\",\n \"eventName\": \"event_name\",\n \"eventTS\": 1591235390353\n}",
"Timestamp" : "2020-06-04T01:49:50.358Z",
"SignatureVersion" : "1",
"UnsubscribeURL" : "url"
}
when I get this body from SQS using code
String message = sqs_message_object.getBody()
Now I create a wrapper class for thie message body as following
public class SQSMessage
{
#JsonProperty("Type")
private String type;
#JsonProperty("MessageId")
private String messageId;
#JsonProperty("TopicArn")
private String topicArn;
#JsonProperty("Message")
private Message message;
#JsonProperty("Timestamp")
private String timestamp;
#JsonProperty("SignatureVersion")
private int signatureVersion;
#JsonProperty("UnsubscribeURL")
private String unSubscribeUrl;
public String getType()
{
return type;
}
public void setType(String type)
{
this.type = type;
}
public String getMessageId()
{
return messageId;
}
public void setMessageId(String messageId)
{
this.messageId = messageId;
}
public String getTopicArn()
{
return topicArn;
}
public void setTopicArn(String topicArn)
{
this.topicArn = topicArn;
}
public Message getMessage()
{
return message;
}
public void setMessage(Message message)
{
this.message = message;
}
public String getTimestamp()
{
return timestamp;
}
public void setTimestamp(String timestamp)
{
this.timestamp = timestamp;
}
public int getSignatureVersion()
{
return signatureVersion;
}
public void setSignatureVersion(int signatureVersion)
{
this.signatureVersion = signatureVersion;
}
public String getUnSubscribeUrl()
{
return unSubscribeUrl;
}
public void setUnSubscribeUrl(String unSubscribeUrl)
{
this.unSubscribeUrl = unSubscribeUrl;
}
}
And I deserialize the json string in to a SQSMessage object using Object Mapper
SQSMessage sqsMessage = null;
try
{
sqsMessage = objectMapper.readValue(message,SQSMessage.class);
}
catch(JsonProcessingException e2)
{
}
all the fields are getting mapped except for Message field .
because its not just a string but another class.
public class Message
{
private String contentType;
private Content content;
private String eventName;
private Date eventTS;
public String getContentType()
{
return contentType;
}
public void setContentType(String contentType)
{
this.contentType = contentType;
}
public Content getContent()
{
return content;
}
public void setContent(Content content)
{
this.content = content;
}
public String getEventName()
{
return eventName;
}
public void setEventName(String eventName)
{
this.eventName = eventName;
}
public Date getEventTS()
{
return eventTS;
}
public void setEventTS(Date eventTS)
{
this.eventTS = eventTS;
}
}
it fils to deserialize the field Message .
how do i Map the message field to Messaeg class as mentioned.
The error I get is
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `domain.Message`
(although at least one Creator exists): no String-argument constructor/factory method to deserialize
from String value ('{\n \"contentType\": \"content_type_value\",\n \"content\": \"content_value\",\n \"eventName\": \"event_name\",\n \"eventTS\": 1591235390353\n}')
at [Source: (String)"{
I am trying to use Jackson to parse sample json as demonstrated below. However, I the parsing doesn't work (fails without any exceptions - as I get an empty string for event.getAccountId(); What could I be doing wrong?
Thanks!
ObjectMapper om = new ObjectMapper();
String json = "{\"_procurementEvent\" : [{ \"accountId\" : \"3243234\",\"procurementType\" : \"view\"," +
"\"_procurementSubType\" : \"Standard Connector\",\"_quantity\" : \"4\", \"_pricePerMonth\" : \"100.00\"" +
",\"_annualPrice\" : \"1200.00\"}]}";
ProcurementEvent event = om.readValue(json, ProcurementEvent.class);
event.getAccountId(); // returns null
#JsonIgnoreProperties(ignoreUnknown = true)
private static class ProcurementEvent {
private String _accountId;
private String _procurementType;
private String _quantity;
private String _pricePerMonth;
private String _annualPrice;
#JsonProperty("accountId")
public String getAccountId() {
return _accountId;
}
public void setAccountId(String accountId) {
_accountId = accountId;
}
#JsonProperty("procurementType")
public String getProcurementType() {
return _procurementType;
}
public void setProcurementType(String procurementType) {
_procurementType = procurementType;
}
#JsonProperty("_quantity")
public String getQuantity() {
return _quantity;
}
public void setQuantity(String quantity) {
_quantity = quantity;
}
#JsonProperty("_pricePerMonth")
public String getPricePerMonth() {
return _pricePerMonth;
}
public void setPricePerMonth(String pricePerMonth) {
_pricePerMonth = pricePerMonth;
}
#JsonProperty("_annualPrice")
public String getAnnualPrice() {
return _annualPrice;
}
public void setAnnualPrice(String annualPrice) {
_annualPrice = annualPrice;
}
}
In the question, try the following approach:
class ProcurementEvents {
private List<ProcurementEvent> _procurementEvent; // + annotations like #JsonIgnoreProperties, getters/ setters, etc.
}
// json from your example
ProcurementEvents events = om.readValue(json, ProcurementEvents.class);
events.get(0).getAccountId();
In a spring rest application context, i'm trying to create a generic response bean.
The purpose is to avoid to create a specific bean for each method.
I'd like to use standard fields, like status and message, by binding various properties to a map.
Consider the following example :
public class ResponseRestDefault extends HashMap {
private String status;
private String message;
public ResponseRestDefault() {
}
public void addParam(String key, String value) {
this.put(key, value);
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
Usage
#RequestMapping(value = "response", method = RequestMethod.GET)
public ResponseEntity<ResponseRestDefault> response() {
ResponseRestDefault response = new ResponseRestDefault();
response.setStatus("success");
response.setMessage("ok");
response.addParam("test", "value");
return ResponseEntity.ok(response);
}
Json result :
{
"test": "value"
}
Does the json result could contain map fields and class properties ?
You need to modify your response class. Make sure you have the getter and setter methods for map.
public class ResponseRestDefault {
private String status;
private String message;
private Map<String, String> map = new HashMap<>();
public ResponseRestDefault() {
}
public void setMap(String key, String value) {
map.put(key, value);
}
public Map<String, String> getMap()
{
return map;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
You will get response in below format :
{
"status": "success",
"message": "ok",
"map": {
"test": "value"
}
}
I have two jsons like these
{
"clientId":"patientId",
"vendorId":"businessKey"
}
{
"patientId":"1234",
"businessKey":"abcd"
}
I have java POJOs created like these
public class Patient{
private String patientId;
private String businessKey;
public String getPatientId() {
return patientId;
}
public void setPatientId(String patientId) {
this.patientId = patientId;
}
public String getBusinessKey() {
return businessKey;
}
public void setBusinessKey(String businessKey) {
this.businessKey = businessKey;
}
}
public class Client {
private String clientId;
private String vendorId;
public String getClientId() {
return clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public String getVendorId() {
return vendorId;
}
public void setVendorId(String vendorId) {
this.vendorId = vendorId;
}
}
I am using Jackson's ObjectMapper to parse the JSON. What I want to achieve is first read the first JSON, get the value from that and then read the actual value from the second JSON.
Ex: I read the first JSON to getClientId - "patientId"
Then in the second JSON I should read getPatientId - 1234.
How do I achieve this programmatically. I dont want to clutter my code by adding lot many if else blocks. Is there any library that I could use?
I am trying to parse the data into a class.
But the problem is that one of the values is in Json format.
Hence I am getting a MalformedJsonException.
This is the Json string:
{
"name": "Check on Server Health ",
"state": "ABORTED",
"startTime": 1332962596131,
"triggeredBy": "GUI_MANUAL",
"completionPct": 25,
"currentStep": "sayHello",
"processDefId": "SW21SW",
"jobRetries": 0,
"businessKey": -1,
"comments": "couldn't instantiate class com.mikewidgets.helloWorld.HelloWorldTask",
"endTime": null,
"status": "DELAY , ERR",
"mtId": "MOTOROLA",
"instParms": "{"message":"start-workflow","sender":"CLI_APP","receiver":"BPM_ENG","parameters":{"workflowId":"SW21SW","mikesname":"Mikeeeeeeey","wf_HostName":"localhost","triggeredBy":"GUI_MANUAL","replyQueue":"temp-queue: //ID: SW-Demo01-51605-1332362748085-0: 2246: 1"},"userId":"Ab","mtId":"MOTOROLA","messageType":"MESSAGE_MSG"}",
"execId": "292",
"startUserId": "Ab"
}
This is the bean class I am using:
import com.google.gson.JsonElement;
public class WfActive {
private String name;
private String state;
private String startTime;
private String status;
private String endTime;
private String comments;
private String triggeredBy;
private String execId;
private JsonElement instParms;
private String startUserId;
private String mtId;
private String businessKey;
private String completionPct;
private String jobRetries;
private String processDefId;
private String currentStep;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getStartTime() {
return startTime;
}
public void setStartTime(String startTime) {
this.startTime = startTime;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getEndTime() {
return endTime;
}
public void setEndTime(String endTime) {
this.endTime = endTime;
}
public String getComments() {
return comments;
}
public void setComments(String comments) {
this.comments = comments;
}
public String getTriggeredBy() {
return triggeredBy;
}
public void setTriggeredBy(String triggeredBy) {
this.triggeredBy = triggeredBy;
}
public String getExecId() {
return execId;
}
public void setExecId(String execId) {
this.execId = execId;
}
public JsonElement getInstParms() {
return instParms;
}
public void setInstParms(JsonElement instParms) {
this.instParms = instParms;
}
public String getStartUserId() {
return startUserId;
}
public void setStartUserId(String startUserId) {
this.startUserId = startUserId;
}
public String getMtId() {
return mtId;
}
public void setMtId(String mtId) {
this.mtId = mtId;
}
public String getBusinessKey() {
return businessKey;
}
public void setBusinessKey(String businessKey) {
this.businessKey = businessKey;
}
public String getCompletionPct() {
return completionPct;
}
public void setCompletionPct(String completionPct) {
this.completionPct = completionPct;
}
public String getJobRetries() {
return jobRetries;
}
public void setJobRetries(String jobRetries) {
this.jobRetries = jobRetries;
}
public String getProcessDefId() {
return processDefId;
}
public void setProcessDefId(String processDefId) {
this.processDefId = processDefId;
}
public String getCurrentStep() {
return currentStep;
}
public void setCurrentStep(String currentStep) {
this.currentStep = currentStep;
}
}
But I am getting a Malformed exception at :
LA","instParms":"{"message":"start-workf // this is inside instParms
What is my mistake and how do I correct it?
Please forgive the big code, the interesting part is "instParms"
Your JSON data is malformed (middle line below):
"mtId": "MOTOROLA",
"instParms": "{"message":"start-workflow","sender":"CLI_APP","receiver":"BPM_ENG","parameters":{"workflowId":"SW21SW","mikesname":"Mikeeeeeeey","wf_HostName":"localhost","triggeredBy":"GUI_MANUAL","replyQueue":"temp-queue: //ID: SW-Demo01-51605-1332362748085-0: 2246: 1"},"userId":"Ab","mtId":"MOTOROLA","messageType":"MESSAGE_MSG"}",
"execId": "292",
Second double quote in the value of instParms should be escaped. Alternatively, one could use single quotes instead if you know that single quotes aren't used in the value.
This is valid:
"mtId": "MOTOROLA",
"instParms": '{"message":"start-workflow","sender":"CLI_APP","receiver":"BPM_ENG","parameters":{"workflowId":"SW21SW","mikesname":"Mikeeeeeeey","wf_HostName":"localhost","triggeredBy":"GUI_MANUAL","replyQueue":"temp-queue: //ID: SW-Demo01-51605-1332362748085-0: 2246: 1"},"userId":"Ab","mtId":"MOTOROLA","messageType":"MESSAGE_MSG"}',
"execId": "292",
and so is this:
"mtId": "MOTOROLA",
"instParms": "{\"message\":\"start-workflow\",\"sender\":\"CLI_APP\",\"receiver\":\"BPM_ENG\",\"parameters\":{\"workflowId\":\"SW21SW\",\"mikesname\":\"Mikeeeeeeey\",\"wf_HostName\":\"localhost\",\"triggeredBy\":\"GUI_MANUAL\",\"replyQueue\":\"temp-queue: //ID: SW-Demo01-51605-1332362748085-0: 2246: 1\"},\"userId\":\"Ab\",\"mtId\":\"MOTOROLA\",\"messageType\":\"MESSAGE_MSG\"}",
"execId": "292",
Another alternative would be to embed the value of instParms as a subobject rather than a stirng:
"mtId": "MOTOROLA",
"instParms": {
"message": "start-workflow",
"sender": "CLI_APP",
"receiver": "BPM_ENG",
"parameters": {
"workflowId": "SW21SW",
"mikesname": "Mikeeeeeeey",
"wf_HostName":"localhost",
"triggeredBy":"GUI_MANUAL",
"replyQueue":"temp-queue: //ID: SW-Demo01-51605-1332362748085-0: 2246: 1"
},
"userId": "Ab",
"mtId": "MOTOROLA",
"messageType": "MESSAGE_MSG"
},
"execId": "292",
This is arguably the best solution (unless there is some other compelling reason to keep the string representation).
You can't readily fix it in the code consuming the JSON, nor should you. You need to fix the other end, which is generating invalid JSON. It looks like just an erroneous quote prior to the { on the value for instParms and after the } at the end of it. That, or the entire instParms value really is meant to be a string, and the string hasn't been properly escaped (quotes preceded with backslashes, etc.).