Remove leading array and / or root element label in produced json - json

My resulting json looks like this:
{"popularPurchases":[
{"product":{"id":"123","face":"face1","size":"1","price":"500"},
"recent":["smith","hambone","someone"]},
{"product":{"id":"222","face":"face2","size":"2","price":"600"},
"recent":["john","mary"]}
]}
My question is how can I get rid of the labels "popularPurchases" (including the ':') and "product (including the ':')?
My POJOs all look the same. Here is one of them:
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class PopularPurchase {
#XmlElement
private Product product;
#XmlElement(name="recent")
private List<String> users;
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
public List<String> getUsers() {
return users;
}
public void setUsers(List<String> users) {
this.users = users;
}
}
I need it to look like this:
[
{"id":"123","face":"face1","size":"1","price":"500"},
"recent":["smith","hambone","someone"]},
{"id":"222","face":"face2","size":"2","price":"600"},
"recent":["john","mary"]}
]
I am producing the JSON with:
PopularPurchaseResponse ppResponse = new PopularPurchaseResponse();
ppResponse.setPopularPurchases(popularPurchases);
builder = Response.status(200).entity(ppResponse);
return builder.build();

Related

JAX-RS Json response comes in one line

This is probably some basic question. I am using JAX-RS (jersey implementation) and my code is as follows.
#Path("/data")
#GET
#Produces(MediaType.APPLICATION_JSON)
public Car handlerFn(#Context HttpServletResponse res)
{
res.setStatus(HttpServletResponse.SC_OK);
Car carObject = new Car(42,"Maruthi", "Alto");
return carObject;
}
Car Entity is as follows
public class Car {
int id;
String name;
String model;
public Car() {
}
public Car(int id, String name, String model)
{
this.id=id;
this.name = name;
this.model = model;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getModel() {
return model;
}
}
The output I am getting is in one line as follows
{"id":42,"model":"Alto","name":"Maruthi"}
In place of this I want the each member in different lines as follows
{
"id": 42,
"model": "Alto",
"name": "Maruthi"
}
How can I do that?

SpringBoot Rest response not deserialiazed with jackson

I am a running a project with SpringBoot. In this project I am calling an external Rest Service. I have modeled the response items into bean.
But when I get the response back the data are not serialised into the beans.
I guess there must be some configuration missing but I cannot find what.
I have added onfiguration spring-boot-starter-test to the configuration of Maven:
The rest client:
#RunWith(SpringRunner.class)
#SpringBootTest
public class RestClientTest {
#Autowired
private RestTemplateBuilder restTemplate;
#Test
public void sayHello() {
System.out.println("Hello");
assert(true);
}
#Test
public void testGetEmployee() {
RestTemplate template = restTemplate.build();;
HttpHeaders headers = new HttpHeaders();
List<MediaType> types = new ArrayList<MediaType>();
types.add(MediaType.APPLICATION_JSON);
types.add(MediaType.APPLICATION_XML);
headers.setAccept(types);
headers.set("Authorization", "Bearer gWRdGO7sUhAXHXBnjlBCtTP");
HttpEntity<Items> entity = new HttpEntity<Items>(headers);
String uri = "https://mytest.com/employees";
//ResponseEntity<String> rec = template.exchange(uri, HttpMethod.GET, entity, String.class);
//System.out.println("Received: " + rec);
ResponseEntity<Items> rec = template.exchange(uri, HttpMethod.GET, entity, Items.class);
System.out.println("Received: " + rec);
}
}
When I inspect the elements of the response it, I get a list, all the items are with null values
#JsonFormat(shape = JsonFormat.Shape.OBJECT)
public class Item implements Serializable {
#JsonProperty
private String id;
#JsonProperty
private String name;
#JsonProperty
private String email;
#JsonProperty
private String phone;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
#JsonFormat(shape = JsonFormat.Shape.OBJECT)
public class Items implements Serializable {
#JsonProperty
private List<Item> items = new ArrayList<Item>();
public List<Item> getItems() {
return items;
}
}
Do you see what I am missing here?
The response is like this:
{
"items": [
{
"item": {
"id": 0,
"name": "string",
"email": "string",
"phone": "string",
Do you see what I am missing here?
Thanks
Gilles
The way you have implemented will try to deserialize data into Items class. But it doesn't have the required properties to deserialize. When you need to get a list of data through rest template exchange, you can get them as follows.
Get data as an array and convert it into arrayList.
Item[] itemArray = template.exchange(uri, HttpMethod.GET, entity, Item[].class).getBody();
List<Item> itemList = Arrays,asList(itemArray);
or
Use ParameterizedTypeReference to get data as a list
ResponseEntity<List<Item>> itemList = template.exchange(uri, HttpMethod.GET, entity, new ParameterizedTypeReference<List<Item>>() {});
List<Item> itemList = template.exchange(uri, HttpMethod.GET, entity, new ParameterizedTypeReference<List<Item>>() {}).getBody(); // access list directly
You might need to add this to your ObjectMapper:
mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
And on your entity add #JsonRootName("item")

JSON object and Multipart file upload not working

We have Angular Controller as follows
$scope.uploadData = function (files, data) {
var fd = new FormData();
fd.append("CustomerName", "Mahesh"); //As of now mocking the entities for creating form data
fd.append("CustomerID ", "44444");
fd.append("ProductList", JSON.stringify([{ProductID: '0001', ProductName: 'Samsung'},{ProductID: '0002', ProductName: 'Voldats'}]));
fd.append("file", files[0]);
fd.append("file", files[1]);
inventoryService.Postfile(fd);
}
Restangular post as follows
Postfile : function (formData) {
return restangular.all("postfile").withHttpConfig({transformRequest: angular.identity}).customPOST(formData, '', undefined, {'Content-Type': undefined});
},
Java VOs as follows
public class ProductList implements Serializable{
private String ProductID;
private String ProductName;
public String getProductID() {
return ProductID;
}
public void setProductID(String productID) {
ProductID = productID;
}
public String getProductName() {
return ProductName;
}
public void setProductName(String productName) {
ProductName = productName;
}
}
and
public class CustomerList implements Serializable{
String CustomerName;
String CustomerID;
List<ProductList> ProductList;
public String getCustomerName() {
return CustomerName;
}
public void setCustomerName(String customerName) {
CustomerName = customerName;
}
public String getCustomerID() {
return CustomerID;
}
public void setCustomerID(String customerID) {
CustomerID = customerID;
}
public List<ProductList> getProductList() {
return ProductList;
}
public void setProductList(List<ProductList> productList) {
ProductList = productList;
}
}
Spring controller as follows
#ResponseStatus(HttpStatus.OK)
#RequestMapping(value = "/api/postfile", method = RequestMethod.POST)
public #ResponseBody
IhmsVO postfile(#RequestParam("file") List<MultipartFile> files,
#ModelAttribute(value = "data") CustomerList vo, BindingResult bindingResult, Model model) {
System.out.println("Post file");
System.out.println(vo.getProductList());
System.out.println("Files :: " + files + " " + files.size());
return null;
}
We have uploaded two files and JSON Object, CustomerName and CustomerID mapped properly with corresponding VO, but ProductList not mapped with the VO.We are getting null in ProductList, Debug mode screenshot attached for refrence. May help to resolve this?
You have to use Blob with correct content type to pass the JSON data and add it to the form (https://developer.mozilla.org/en/docs/Web/API/Blob), e.g.:
fd.append("ProductList", new Blob([ JSON.stringify([{ProductID: '0001', ProductName: 'Samsung'},{ProductID: '0002', ProductName: 'Voldats'}]) ], { type: "application/json" }));
EDIT: Updated the code to be absolutely clear and avoid any typos, case sensitivity issues, wrong placement of parenthesis etc.

Jersey+jackson - how to serialize generic list

I have a problem with converting my lists to JSON. I'd like to use generic lists with templating.
This doesn't work for me. My POJO:
class Event {
private Long id;
public void setId(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
}
Generic list result:
public class ListResponse<T> {
private List<T> result = new ArrayList<T>();
public List<T> getResult() {
return result;
}
public void setResult(List<T> result) {
this.result = result;
}
}
Concrete list result:
public class EventListResponse extends ListResponse<Event> {}
In my resource class I'm using this:
#PermitAll
#Path("/list")
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public EventListResponse getEvents() {
//...
EventListResponse response = new EventListResponse();
List<Event> events = eventService.getList();
response.setResult(events);
return response;
}
The serialize doesnt work in this case, I end up with Strings insead of "Event" JSON objects.
I get results like:
array(3) { ["type"]=> string(17) "eventListResponse" ["result"]=> array(1) { [0]=> string(38) "com.mypackage.model.Event#3a622482" } }
Whats the problem here?
Thank you

Remove type-information from JSON result

Currently I am trying to create a webservice which simply returns a list;
#Path("/random")
#Singleton
public class Random
{
#GET
#Path("/")
#Produces(MediaType.APPLICATION_JSON)
public MyResult<String> test()
{
MyResult<String> test = new MyResult<String>();
test.add("Awesome");
return test;
}
}
And my MyResult class looks like this:
#XmlRootElement
public class MyResult<T> implements Iterable<T>
{
private ArrayList<T> _items;
private int _total;
public MyResult()
{
_items = new ArrayList<T>();
}
public ArrayList<T> getItems()
{
return _items;
}
public void setItems(ArrayList<T> items)
{
_items = items;
}
public int getTotal()
{
return _total;
}
public void setTotal(int total)
{
_total = total;
}
public void add(T item)
{
getItems().add(item);
}
public Iterator<T> iterator()
{
return getItems().iterator();
}
}
Now I get the following result from the service:
{"items":[{"#type":"xs:string","$":"Awesome"}],"total":"0"}
But I don't want any of this information, I just require this:
{"items":["Awesome"],"total":"0"}
It seems to me this requires some configuration somewhere, who know how to get the required result?
Assuming you are using jackson, take a look at #JsonTypeInfo annotation. It is used for configuring details of if and how type information is used with JSON serialization and deserialization. The use and behaviour of it would depend on the version of jackson you are using.
To completely suppress type information, I had to use the following annotations:
#JsonTypeInfo(use=JsonTypeInfo.Id.NONE)
#JsonDeserialize(as=NoType.class)