I have to transform a very peculiar JSON payload into POJOs manually. I thought I could put the JSON string into a String entity:
#ApiMethod(
name = "postSomething",
path = "postSomething/{id}",
httpMethod = ApiMethod.HttpMethod.POST
)
public void postSomething(#Named("id") Integer id, HttpServletRequest request, String data) {
//Parse data here...
}
When I do that, I get an error: MissingParameterNameException: Missing parameter name. Parameter type (class java.lang.String) is not an entity type and thus should be annotated with #Named.
I tried to use an #ApiTransformer but I get a similar error.
Could you please give me an example of parsing the JSON content manually?
The error message says that String data needs to have an #Named annotation, similar to Integer id.
I worked around this issue by using a Collections class instead of String and manual parsing:
#ApiMethod(
name = "postSomething",
path = "postSomething/{id}",
httpMethod = ApiMethod.HttpMethod.POST
)
public void postSomething(#Named("id") Integer id, HttpServletRequest request, HashMap<String,String> data) {
//Parse each item of data here...
}
From this, I can parse each item inside the data. The values contain a hierarchy of either other collections (List for an array, Map for a JSON entity) or String for an actual value. So by doing this I don't need to use any other JSON parsing library such as Jackson.
String is not an #Entity object so it can't be passed as a parameter (a data parameter) to the endpoints API without proper annotation (like #Name or #Nullable). Either you must remove it from the method declaration or annotate it with #Name or #Nullable.
Related
So I have this variable specCifDetailsReturn which contains the ff. payload
[
{"ax21:cHType":"S",
"ax21:cardNumber":4***********7126,"ax21:returnCde":"00",
"ax21:cancelCode":"",
"ax21:vipCode":"",
"ax21:custrNbr":"0*****3426"},
{"ax21:cHType":"S",
"ax21:cardNumber":4***********3038,"ax21:returnCde":"00",
"ax21:cancelCode":"H",
"ax21:vipCode":"",
"ax21:custrNbr":"0*****3426"}
]
And the ff. Model Class to extract the params I need from the Array
#Data
#AllArgsConstructor
#NoArgsConstructor
#JsonNaming(PropertyNamingStrategy.UpperCamelCaseStrategy.class)
public final class SpecCifInfo {
#JsonAlias("ax21:cHType")
private String cHType;
#JsonAlias("ax21:cardNumber")
private String cardNumber;
}
I am trying to convert it to a Java ArrayList so that I could loop into it and find a card number. But for some reason it always throws a null value on the log even though the specCifDetailsReturn variable has a value. Below is the snippet of my code.
Gson gson = new Gson();
Type type = new TypeToken<List<SpecCifInfo>>(){}.getType();
ArrayList<SpecCifInfo> specDetails = gson.fromJson(specCifDetailsReturn.toString(),type);
for (SpecCifInfo specInfo : specDetails){
LOGGER.debug("Spec CIF Details", specInfo.getCHType() + "-" + specInfo.getCardNumber());
}
Sample Output of the SpecCifInfo Object that has null values
Those annotations are for the Jackson library, and you are manually using Gson. You should either keep them and just let Spring handle the deserialization for you by specifying a List<SpecCifInfo> parameter in the controller method, or you should use GSON's #SerializedName annotation. Either way will work.
My main question is how to pass a (Map, String) to a REST API, I know if I use #RequestBody all the passed contents are stored to map but what can be done to pass map as well as any other parameters REST API.
#GetMapping(path="/invoices")
public String invoiceReceived( Map<String,Object> invoice,String format) throws MessagingException {
System.out.println(format); // this prints NULL
return "returnValue";
}
So I tried using PathVariable but they throw exception. What can be done?
#GetMapping(path="/invoices/{invoiceData}/{format}")
public String invoiceReceived(#PathVariable("invoiceData") Map<String,Object> invoice,
#PathVariable("format") String format) throws MessagingException {
System.out.println(format); // this prints NULL
return "returnValue";
}
What should I do to accept a map and a variable as input? And what should be the JSON file look like which should be given as input?
{
"invoiceData":[{"invoiceId":"23642",
"clientName":"Client",
"amount":"23742.67",
"email":"client#abc.com"
}],
"format":"html"
}
This question was identified similar to another question, So I am trying to explain how is this different, I know that I can use #RequestBody to get all the variables in the map, but The call will be made with two parameters some of which will be stored in map but one parameter will be used for another variable. So how can I send a map along with any other variable?
I think you can use query strings and path variables.
If you declare a controller's method like:
#GetMapping(path="/invoices")
public String invoiceReceived(#RequestBody Map<String,Object> invoice, #RequestParam String format) {
...
}
the url to which the request is send and the JSON request body will be something like below.
The url:
http://localhost:8080/invoices?format=html
The JSON request body:
{
"invoiceId":"23642",
"clientName":"Client",
"amount":"23742.67",
"email":"client#abc.com"
}
Also you can use a path variable like:
http://localhost:8080/invoices/html
#GetMapping(path="/invoices/{format}“)
public String invoiceReceived(#RequestBody Map<String,Object> invoice, #PathVariable String format) {
...
}
I try to read Json file with Jackson and depends on it, make another Json output. The problem is to read Json file, I created a POJO object with fields, that represent in Json. But it could change and there are could be appear another values, that I didn't represent in POJO. So my logic there, is will add fields, depends on read values I've been get from Json. Is there are any way to do this, or I came not right way..
public String makeOutput() {
Collection<String> key = map.get("POJO");
for (String name : key) {
requestOut = mock.reflect(CAPM.class)
.field("name", "Anna")
.field("age", 12)
// there is field 'name', that didn't represent in POJO
.field(name, "Green")
.map(gson::toJson)
.val();
}
return requestOut;
}
I'm using mockNeat lib. for generate Json. "map" is a MultiValuedMap<String, String>
I am using Java Spring with version 2.0.0 Snapshot of AMQP. I create an AMQP message, send it. In another service I am receiving the message correctly, except the headers instead of receiving type Object, every header is of type String.
Publisher Code:
Message responseMessage = MessageBuilder
.withBody(SerializationUtils.serialize(person))
.setContentType(MessageProperties.CONTENT_TYPE_SERIALIZED_OBJECT)
.setHeader("STUDENT_TYPE", "New") // Not part of person object but related
.setHeader("PET", getPet()) // This is a pet object
.build();
rabbitTemplate.send(responseMessage);
Consumer Code:
Object messageBody = SerializationUtils.deserialize(amqpMessage.getBody());
Person person = (Person)messageBody;
MessageProperties properties = amqpMessage.getMessageProperties();
String type = properties.getHeaders().get("STUDENT_TYPE").toString();
Pet pet = (Pet)properties.getHeaders().get("PET");
When I run the above code, I will fail on the last line of the consumer code with the error: Cannot cast String to Pet. The message comes across ok, except every header is of type String when received in the consumer code.
USAGE: MessageBuilder.setHeader(String Key, Object Value);
USAGE: Properties.getHeaders() returns Map<String,Object>
Every header has key/value pair of type String/Object. The work around I have in place is also serializing an header I would like to pass non-string/integer values for, but this seems to be besides the point of the header. Am I missing something?
You need to serialize your Pet to a string, and deserialize it when you get it in another service. E.g. you can use fasterxml Jackson and serialize it to JSON string
You are telling the compiler your String is really a Pet. However, Pet is not a subclass of String. There are two possible solutions:
Solution1: You make sure Pet extends String, like this:
public class Pet extends String {
//...
}
and then you will be able to cast String into Pet.
Solution2: You implement a constructor of Pet which takes a String as parameter:
public class Pet {
//...
Public Pet(String name) {
//...
}
//...
}
Am working on a REST API. This sample here works fine but am really confused about something here. My method getAll returns a String but the method has been annotated to Produce MIME MediaType of JSON. My question is , is the final returned response (doc) a JSONObject or just a json String(Thus a String in JSON format). So that I can know how to handle the response when I get it.
#Path("/membership/{pageNumber}")
#GET
#Produces("application/json")
public String getAll(#PathParam("pageNumber") String pageNumber){
Map<String , String > params = new HashMap<>();
String doc = HTTPClient.sendGet("localhost:9500/users/list/membership/field/"
+pageNumber, params, 60);
return doc;
}
This will really help me in my documentation as well.
All efforts are appreciated,Thanks.
My question is , is the final returned response (doc) a JSONObject or
just a json String(Thus a String in JSON format)
Yes it will return the json String,If you want to send JSON and HTTP Status together you can use Response as your return type.
Example:
#GET
#Path("/testGet")
#Produces("application/json")
public Response testGet() {
String json = //Create JSON String
return Response.ok(json, MediaType.APPLICATION_JSON).build();
}
You finally produce a JSON string.
Instead of just returning String it is recommended to use Entity
return Response.ok().entity(doc).build();
What is Actually Returned by a Method
Exactly what you return. This is Java. That is how Java works. There is not magic voodoo.
Maybe you're wondering something else.
All responses are written to the response output stream. It doesn't matter what the return type is. What matters is that there is a MessageBodyWriter that knows how to write that type to the output stream based on the #Produces content type. If the return type is a String, then there needs to be a writer that knows how to handle String-application/json combination. If the return type is JSONObject, then there need to be a writer that can handle that.
See Also: JAX-RS Entity Providers
The client needs to know nothing about any Java types (i.e. Sting, JSONObect, etc). It gets the data a stream of bytes and converts the data with whatever conversion method it uses.