my vo class here:
public class Code {
private String key;
private long number;
private long number2;
private long number3;
}
and, rest request body example below.
{
key: '12',
number: chjxdghdxfg',
number2: 45,
number3: 'ggg'
}
use new Gson().fromJson(json, Code.class) casued NumberFormatException.
how to validate json payload in the example above?
i hope so get error fields like: 'number', 'number3'
Related
I have complex object and I want to render it, but I have several problems in view.
First of all, I have UUID field in my class but in View I get not the String but mostSigBits and leastSigBits.
The second one, I have my enums fields like two fields with enum and value
For example,
public class ExampleObject {
#JsonProperty("id")
private UUID id;
#JsonProperty("name")
private String name;
#JsonProperty("address")
private String address;
#JsonProperty("port")
private String port;
#JsonProperty("users")
#Valid
private List<UserRef> users = null;
#JsonProperty("indexingParameters")
private IndexingParameters indexingParameters;
#JsonProperty("otherParameters")
private OtherParameters otherParameters;
#JsonProperty("status")
private Status status;
}
When I get response from controller I get answer with this one
{
"id": {
"leastSignificantBits": -5406850341911646206,
"mostSignificantBits": 8884977146336383467
},
"status": {
"enumType": "api.model.Status",
"name": "GENERAL"
}
....
}
The problem is I have a lot of different but with the same problem objects in my code. If there is only 1 object, I`d easy prepare some _exampleObject.gson template and render every answer from controller to it, but I have many objects.
I think there are some variants to render correct my JSON, isn`t there?
Another rendering variants where data is ExampleObject.class or something like that
1)code:
Map map = [content: data.content, sorting: data.sorting, paging: data.paging] as Map
render AppResponse.success([success: true, data: map]).asJSON()
render data as JSON
on front:
Incorrect UUID and DateTime convert each field in Object, But I need Timeshtamp
"id": {"leastSignificantBits": -5005002633583312101,
"mostSignificantBits": 4056748206401340307},
"key": "b48d35dd-0551-4265-a1b1-65105e713811",
2)code:
Map map = [data: new ObjectMapper().writeValueAsString(data)] as Map
render map
on front:
Here we can see square brackets at the start which is wrong for JSON
['data':'{"content":[{"id":"384c7700-09c1-4393-ba8a-a89f555f431b","name":"somename"...
3)code:
Object result = new HashMap<String, Object>()
result.success = true
result["data1"] = new ObjectMapper().writeValueAsString(data)
render result as JSON
on front:
Here we can see quotes escaping
"data": "{\"content\":[{\"id\":\"384c7700-09c1-4393-ba8a-a89f555f431b\",\"name\":\"somename\",\"key\":\"b48d35dd-0551-4265-a1b1-65105e713811\",\"status\":\"COMPLETED\.......
I did it like this
#CompileStatic
class MyProxyController {
#Autowired
Myservice service
static ObjectMapper objectMapper = new ObjectMapper()
.registerModule(new JodaModule())
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false)
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
def getExampleObject {
ExampleObject exampleObject = service.getExampleObject()
render([contentType: "application/json"], objectMapper.writeValueAsString(new CustomObject(data, true)))
}
#CompileStatic
class CustomObject {
Boolean success
Object data
CustomObject(Object data, Boolean success) {
this.data = data
this.success = success
}
}
}
And get json as I wanted like
{
"success": true,
"data": {
"content": [
{ ....
I am trying to create a custom JsonAdapter for my JSON data that would bypass the serialization of specific field. Following is my sample JSON:
{
"playlistid": 1,
"playlistrows": [
{
"rowid": 1,
"data": {
"123": "title",
"124": "audio_link"
}
}
]
}
The JSON field data in above have dynamic key numbers, so I want to bypass this data field value and return JSONObject.
I am using RxAndroid, Retrofit2 with Observables. I have created a service class:
public static <S> S createPlaylistService(Class<S> serviceClass) {
Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(baseURL)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(httpClientBuilder.build())
.addConverterFactory(MoshiConverterFactory.create());
return builder.build().create(serviceClass);
}
I am calling this service using observable like this:
#GET("http://www.mylink.com/wp-json/subgroup/{subgroupId}/playlist/{comboItemId}")
Observable<Playlist> getPlaylist(#Path("subgroupId") int subgroupId, #Path("comboItemId") int comboItemId);
Then I run it like this:
ServiceBuilder.createPlaylistService(FHService.class).getPlaylist(123, 33);
My Pojo classes look like this:
public class Playlist {
#Json(name = "playlistid")
public Long playlistid;
#Json(name = "playlistrows")
public List<Playlistrow> playlistrows = null;
}
public class Playlistrow {
#Json(name = "rowid")
public Long rowid;
#Json(name = "data")
public Object data;
}
The problem is it would return a data value in this format:
{
123=title,
124=audio_link
}
which is invalid to parse as JSONObject.
I have Googled a lot and have also checked some Moshi example recipes but I had got no idea about how to bypass this specific field and return valid JSONObject, since I am new to this Moshi library.
I followed code from this example but my toJSON() function is not called.
Attempt 1
export class Template {
constructor(
) {}
public id: string
public account_id: string
public name: string
public title: string
public info: string
public template_items: Array<number>
public toJSON = function() {
return {
attributes: this.template_items
}
}
}
Attempt 2
interface ITemplateSerialized {
attributes: Array<number>
}
export class Template {
constructor(
) {}
public id: string
public account_id: string
public name: string
public title: string
public info: string
public template_items: Array<number>
toJSON(): ITemplateSerialized {
return {
attributes: this.template_items
}
}
}
Attempt 3
Identical code to Attempt 2 except the toJSON is:
public toJSON = function(): ITemplateSerialized {
return {
attributes: this.template_items
}
}
Create some data...eg:
let t = new Template();
t.name = "Mickey Mouse"
t.template_items = [1,2,3]
console.log(JSON.stringify(t));
In all cases it does not change template_items to attributes...what am I missing here?
UPDATE
The provided plunk by #estus in the comments worked, so I decided to make one in Angular, to compare. Here it is and it works.
When I wrote the question, to make the code simple to understand, I had made 'template_items' an array of numbers. But in my actual Angular project it is an array of custom objects. Here is a plunker showing that structure. It also works. And another plunker working in Angular 4.4.6
But this identical setup does not work in my Angular project. So the question stands in case anyone else can reproduce this?
In my project I get a completely empty object returned from JSON.stringify().
So, it seems I was confused between how toJSON() works and how stringify replacer function works.
With toJSON() the function you supply will ONLY return the items you specify. I was under the impression that it would return all properties and ONLY change the ones you specify in the function.
So in my project there were no template_items at the point the object was first created, and since that was the ONLY property my serialized interface specified all the other properties were being removed, hence an empty object.
So, the solution is to specify ALL properties, in both the function return statement and in the serialize interface:
toJSON(): ITemplateSerialized {
return {
id: this.id,
account_id: this.account_id,
name: this.name,
title: this.title,
info: this.info,
attributes: this.template_items
}
}
export interface ITemplateSerialized {
id: string,
account_id: string,
name: string,
title: string,
info: string,
attributes: Array<TemplateItem>
}
I'm using Postman to test REST Web API and I have a method that receives this object:
public class NewShipmentDto implements Serializable {
private String description;
private Long senderId;
private Long receiverId;
private byte[] packageImage;
private CommissionPaidBy commissionPaidBy;
private Long senderPaymentMethod;
private LocationDto senderLocation;
private LocationDto receiverLocation;
// + constructors and gets/sets
}
So the body of my POST needs to be something like this:
{
"description":"Libros",
"senderId":1,
"receiverId":1,
"commissionPaidBy":"BOTH",
"senderPaymentMethod":1,
"senderLocation":
{
"latitud":100,
"longitud":100
},
"receiverLocation":
{
"latitud":100,
"longitud":100
}
}
But I also need to send the file so it can be transformed to a byte []. The thing is if I use form data to pass the file how do I send this bits:
"receiverLocation":
{
"latitud":100,
"longitud":100
}
Is it possible to send nested json in the form data?
This is my POST method, I haven't added the logic of reading the file yet:
#POST
#Consumes({MediaType.APPLICATION_JSON})
#Produces({MediaType.APPLICATION_JSON})
public Response addShipment(String shipment) throws EnviosYaException {
Gson gson = new Gson();
NewShipmentDto newShipmentDto = gson.fromJson(shipment, NewShipmentDto.class);
NewShipmentResponseDto response = shipmentServices.addShipment(newShipmentDto);
return Response.ok(gson.toJson(response)).build();
}
If necessary I could change the structure of the json to avoid having nested json, but I would like to know if it's possible first.
Thanks
It looks like you are using JAX-RS for the REST API. For your use case multipart/format-data content-type is more appropriate.
Please have a look at this JAX-RS question.
Or
If you like keep the JSON structure intact, you can store the base64 encoded data in a string for the image field. The model would looks like.
public class NewShipmentDto implements Serializable {
private String description;
private Long senderId;
private Long receiverId;
private String encodedPackageImage;
private CommissionPaidBy commissionPaidBy;
private Long senderPaymentMethod;
private LocationDto senderLocation;
private LocationDto receiverLocation;
// + constructors and gets/sets
}
I am using JAX-RS (CXF) with JaxB and Jackson to provide a REST-API.
Unfortunately, none of the found results helps me with following (simple) problem:
I implemented following method:
#POST
#Path(ApiStatics.ARMY_CREATE_ARMY)
public com.empires.web.dto.Army createArmy(#FormParam("locationid") long locationId, #FormParam("name") String name, #FormParam("troops") ArmyTroops troops) {
and here are is my model class:
#XmlRootElement
#XmlSeeAlso(ArmyTroop.class)
public class ArmyTroops {
public ArmyTroops() {
}
public ArmyTroops(List<ArmyTroop> troops) {
this.troops = troops;
}
#XmlElement(name = "troops")
private List<ArmyTroop> troops = new ArrayList<ArmyTroop>();
public List<ArmyTroop> getTroops() {
return troops;
}
public void setTroops(List<ArmyTroop> troops) {
this.troops = troops;
}
}
ArmyTroop
#XmlRootElement(name = "troops")
public class ArmyTroop {
#XmlElement
private long troopId;
#XmlElement
private String amount;
public long getTroopId() {
return troopId;
}
public void setTroopId(long troopId) {
this.troopId = troopId;
}
public String getAmount() {
return amount;
}
public void setAmount(String amount) {
this.amount = amount;
}
}
My json that i send looks like this:
locationid 1
name asdasd
troops {"troops":[{"troopId":4,"amount":"5"},{"troopId":6,"amount":"5"}]}
Unfortunately, the object gets not transformed. Instead I receive this error:
InjectionUtils #reportServerError - Parameter Class com.empires.web.dto.in.ArmyTroops has no constructor with single String parameter, static valueOf(String) or fromString(String) methods
If I provide the constructor with a single string parameter, I get passed the whole json string for "troops" as mentioned above.
Any ideas why JaxB does not work at this point?
You are passing all your parameters with #Form annotation.
But the Form part of the http message must be an xml data structure.
Your 3 parameters don't have a main xml datastructure so it wont work.
In short, form params are send as body.
Cxf use the MultivaluedMap to send params (cxf have an xml model for this structure).
As you can see it is not fit for parameters that can't be trivally serialized.
Here me solution would be to drop the #FormParam to avoid the problem:
1) Use #PathParam #CookieParam to send yours first 2 parameters, and the 'no tag' (body) only for the army compositions.
2) Define an uber object that take all parameters and can be serialized as xml datastructure and use the 'no tag' (body) sending.
3) Use soap, with cxf it is really easy to gets both Rest and Soap.