Apex - Displaying a list after deserialising json - json

I would like to make a http callout to import json and display the information in a visualforce page. The problem I'm having is that the json is nested and so I need to loop through the child nodes.
I have the following class derived using the json2apex application:
public class CHForm {
public class FilingHistoryItem {
public String DocumentDate;
public String FormType;
public String DocumentCategory;
public String Document;
public String DocumentDescription;
}
public FilingHistory FilingHistory;
public class FilingHistory{
public List<FilingHistoryItem> FilingHistoryItem;
}
public static CHForm parse(String json) {
return (CHForm) System.JSON.deserialize(json, CHForm.class);
}
}
In my controller class I can create a CHForm object (reponseForm) and deserialise the json into the reponseForm object using the following:
HttpResponse res = h.send(req);
String chFormJson = res.getBody();
responseForm = CHForm.parse(chFormJson);
but how do I then display a list of all FilingHistoryItem in the visualforce page? Do I need to create a list object in my controller or is there a way of directly referencing the list from the visualforce page?

I'm a bit confused by your apex, shouldn't it be :
public List<FilingHistoryItem> FilingHistory;
public class FilingHistoryItem {
public String DocumentDate;
public String FormType;
public String DocumentCategory;
public String Document;
public String DocumentDescription;
}
Then you'd be able to do:
<apex:repeat value="{!responseform.FilingHistory.}" var="item" id="theRepeat">
<apex:outputText value="{! item.DocumentDate}" /> //etc
</apex:repeat
The way you've set it up now, I think it may work like this:
<apex:repeat value="{!responseform.FilingHistory.FilingHistoryItem}" var="item" id="theRepeat">
<apex:outputText value="{! item.DocumentDate}" /> //etc
</apex:repeat
But it's a bit strange you name a list property as "...Item" and not "..Items", and nest so deeply, but maybe that's a json dependency.

Related

How to access nested Json Object Value into JPA Entity Class

I have a payload like this
{
"eventId":"ep9_0579af51",
"eventTime":"5/11/2022 5:50:58 PM",
"eventType":"UpdateTransaction",
"meta":{
"userId":"vkp",
"resourceType":"Transaction/DataDocs"
}
}
I need to map this json fields into a single entity class .
#PostMapping(path = "/id", consumes = "application/json")
public ResponseEntity<ImportTrans> import(#RequestBody ImportTrans importTrans) {
return ResponseEntity.of(Optional.ofNullable(repository.save(importTrans););
}
#Table(name = "IMPORT_TRANS")
#Entity
public class ImportTrans implements Serializable {
#Id
private Long processId;// AutoGenerator
private String eventId;
private Date eventTime;
private String eventType;
private String userId; // I dont want create new class for meta . Is there any way i
//can access meta.userId in ImportTrans class.
private String resourceType;
}
How can I access data from meta from ImportTrans without creating a separate class for it?
You should modify your request body before reaching the controller.
"You must consider the application performance factors on your own
before implementation"
Option 1. Using RequestBodyAdvice.
Option 2. Using Spring HandlerInterceptor.
Option 3. Use AOP
Option 4. Using HTTP Filter.
The below solution only works if you are using a separate DTO class.
private Map<String, String> meta = new HashMap<>();
String userID = importTrans.getMeta().get("userId");
I hope the above pieces of information answered your question.

Postman - Sending image file and json on POST

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
}

Not null object but empty json

I have a JAX-RS method that returns me a List with DO's. Unfortunetly when I go to the path which is mapped by the method i get only an empty json list like:
[{}, {}, {}]
My resource method looks like this:
#GET
#Produces("application/json")
public List<ModelDO> getModels() {
List<ModelDo> models = modelRepo.findAllModelsWithName("Name");
return models;
}
I'm 100% sure the objects exists and the list isn't empty, because I have checked it in the debugger.
The ModelDO class is a simple POJO:
public class ModelDO {
private int id;
private String name;
//public getters
}
What should I do to get an non empty json response?
PS. When I'm returning a single object I get the same problem -> {}
EDIT:
modelRepo:
public List<ModelDO> findAllModelsWithName(String name){
return new JPAQueryFactory(entityManager).selectFrom(modelEntity)
.where(modelEntity.name.eq(name))
.fetch();
}
ModelRepo.class is #Injected into my Resoure class
The reason was that my Model object did not have field setters, only getters.

JAX-RS - JSON List to Object with JaxB

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.

WCF JSON serialization on object with IXmlSerializable

I have structure IntEx - in short it extends normal Int32 and processed operation. It looks like this:
[Serializable]
public struct IntEx
{
private int internalValue;
private IntEx(int value)
{
internalValue = value;
}
public static implicit operator int(IntEx value)
{
return value.internalValue;
}
public static implicit operator IntEx(int value)
{
return new IntEx(value);
}
}
If we send this structure through WCF it serialize using JSON and output will "nicely look". Like we will use sample code below:
DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(TestClass));
using (MemoryStream stream = new MemoryStream())
{
jsonSerializer.WriteObject(stream, testClass);
string serializedString = Encoding.UTF8.GetString(stream.GetBuffer());
Console.WriteLine("JSON: {0}", serializedString);
}
public class TestClass
{
public int I1 { get; set; }
public IntEx I2 { get; set; }
}
Output look like this
JSON: {"I1":11,"I2":{"internalValue":22}}
Client and other "third-part" progam use this format (with internalValue).
Using IntEx is widely use in my application. One of the object is serialized to XML (some kind of setting). This object use IntEx as type.
So I have to implement IXmlSerializable to structure IntEx, because without this property is serialized like empty node
XML: <TestClass><I1>11</I1><I2 /></TestClass>
If I change IntEx to use IXmlSerializable
[Serializable]
public struct IntEx : IXmlSerializable
{
private int internalValue;
private IntEx(int value)
{
internalValue = value;
}
public static implicit operator int(IntEx value)
{
return value.internalValue;
}
public static implicit operator IntEx(int value)
{
return new IntEx(value);
}
System.Xml.Schema.XmlSchema IXmlSerializable.GetSchema()
{
return null;
}
void IXmlSerializable.ReadXml(System.Xml.XmlReader reader)
{
throw new NotImplementedException();
}
void IXmlSerializable.WriteXml(System.Xml.XmlWriter writer)
{
writer.WriteValue(internalValue);
}
}
XML output look ok
XML: <TestClass><I1>11</I1><I2>22</I2></TestClass>
but all my service break down, since now JSON look like this:
JSON: {"I1":11,"I2":"<IntEx xmlns=\"http:\/\/schemas.datacontract.org\/2004\/07\/TestJSONSerialization\">22<\/IntEx>"}
I read that if you use IXmlSerializable, JSON serialization "think" that I'm responsible for serialize so leave this object to me... But how can I change back to "original" serialization.
So now I'm in deadend... I need JSON output look like before, but I also need to some how force to write setting to XML with two conditions:
internalValue should remain private - it shouldn't be accessible using some public Property
I don't want rewrite bunch of code to chaneg (use boxing for JSON's properties) or change all possible property or class that can be saved to XML file.
So can anyone give me some clue, how I can resolve this issue? :/
you can use DataContractJsonSerializer with IDataContractSurrogate. using the IDataContractSurrogate to convert "IntEx" to "IntExJson", and the "IntExJson" don't need to inherit from IXmlSerializable.
IDataContractSurrogate can be used to remove some features from object, and convert to the similar object. and then use:
public DataContractJsonSerializer(Type type, IEnumerable<Type> knownTypes, int maxItemsInObjectGraph, bool ignoreExtensionDataObject, IDataContractSurrogate dataContractSurrogate, bool alwaysEmitTypeInformation);
to serialize the object to json. the deserialization is same.