I have code in my android project that correctly deserializes json into POJO's using gson. I wish to add some condtional acceptance checks (sanity checks) to the incoming json. For instance, with the data structure below, I wish for the gson parser to only add objects where the start date < end date. I know I could iterate through the list after it is populated to remove invalid items, but I was wondering if there was any way to reject the items on the fly. Any help would be appreciated.
Example JSON
{
"Items" : [
{
"Name" : "Example Name",
"Start" : "2010-10-16 10:00:00",
"End" : "2011-03-20 17:00:00",
<other fields>
},
<several more items>
]
}
ItemList.java
public class ItemList {
private List<ItemHeader> Items;
public void setItemHeaders(List<ItemHeader> headers) {
Items = headers;
}
public List<ItemHeader> getItemHeaders() {
return Items;
}
}
ItemHeader.java has fields for name, start, end and all the other fields.
You'd need to write your own deserializer and have it throw an exception when your condition isn't met.
http://sites.google.com/site/gson/gson-user-guide#TOC-Writing-a-Deserializer
I don't know that you should do this, but it's possible.
Related
I am trying to figure out how to return multiple JSON items. Right now I am able, to return a single JSON like so:
{
"result": {
"userId": "abcde123",
"telephoneNumber": "1-555-5555555"
},
"error": null
}
But I would like to return multiple JSON items, like so:
{
"result": {{
"userId": "abcde123",
"telephoneNumber": "1-555-5555555"
}
{
"userId": "fghi456",
"telephoneNumber": "1-333-3333333"
}
},
"error": null
}
I can view the multiple JSON items as string, like below, but I would like to return it as multiple JSON items, but I don't know how:
[LDAPModel(userId=abcde123, telephoneNumber=1-555-5555555), LDAPModel(userId=fghi456, telephoneNumber=1-333-3333333]
I am a complete beginner in Java, and I don't know the syntax or much in Java. But I was given these codes (including the one below) from SpringBoot; I really don't understand what it is doing, and so I have no idea how create an output of list.
Currently, this is what I was given:
public Optional<LDAPModel> getDirectReports(String cdsID) {
LdapQuery ldapQuery = LdapQueryBuilder.query()
.searchScope(SearchScope.SUBTREE)
.where("objectclass").is("person")
.and("managerID").like(cdsID);
List<LDAPModel> ldapModelList = ldapTemplate.search(ldapQuery, (Attributes attrs) ->
LDAPModel.builder()
.userId(getValue(attrs, "userid"))
.telephoneNumber(getValue(attrs, "phoneNumber"))
.build());
// for (int ii = 0; ii < ldapModelList.size(); ii++) {
// Optional.of(ldapModelList.get(ii));
// ldapModelList.isEmpty() ? Optional.empty() : Optional.of(ldapModelList.get(ii));
// }
return ldapModelList.isEmpty() ? Optional.empty() : Optional.of(ldapModelList.get(0));
}
I tried putting it in a loop (like in the commented out code above), but I don't know how create a list. I tried removing the get(0), but there was a syntax error... There are many things I tried, but it just did not help.
Anyone can help?
Update/Edit: Thank you all for your answers. I posted a follow up question here. If you have a chance, please help me out. Thanks.
First of all I would like to point out that your JSON isn't formatted properly. When you want to represent multiple objects in JSON you should use square brackets and separate each object with a comma:
{
"result": [
{
"userId": "abcde123",
"telephoneNumber": "1-555-5555555"
},
{
"userId": "fghi456",
"telephoneNumber": "1-333-3333333"
}
],
"error": null
}
The reason your Java code does not work when you try and remove get(0) is because the method public Optional<LDAPModel> getDirectReports(String cdsID) returns an Optional<LDAPModel> type and by removing get(0) your are effectively trying to return an Optional<List<LDAPModel>>. If you want the method to return a list instead of a single object you can change the return type to Optional<List<LDAPModel>> and then safely remove get(0).
public Optional<List<LDAPModel>> getDirectReports(String cdsID) {
LdapQuery ldapQuery = LdapQueryBuilder.query()
.searchScope(SearchScope.SUBTREE)
.where("objectclass").is("person")
.and("managerID").like(cdsID);
List<LDAPModel> ldapModelList = ldapTemplate.search(ldapQuery, (Attributes attrs) ->
LDAPModel.builder()
.userId(getValue(attrs, "userid"))
.telephoneNumber(getValue(attrs, "phoneNumber"))
.build());
return ldapModelList.isEmpty() ? Optional.empty() : Optional.of(ldapModelList);
}
The structure looks strange to me. What you have looks like you want result to be an array of objects:
{
"result": [
{ "userId": "abcde123",
"telephoneNumber": "1-555-5555555" }
{ "userId": "fghi456",
"telephoneNumber": "1-333-3333333" }
],
"error": null
}
Given a reasonable JSON library, then the value of the "result" member of the JSON object is a JSON array, from which you can then pick out each element in turn by indexing, and each element is a JSON object with 2 members.
I assume you already managed to get all the list/array of LDAPModel i.e. List ldapModelList
If so, you just need to return this ldapModelList in your getDirectReports method.
public List<LDAPModel> getDirectReports(String cdsID) {
LdapQuery ldapQuery = LdapQueryBuilder.query()
.searchScope(SearchScope.SUBTREE)
.where("objectclass").is("person")
.and("managerID").like(cdsID);
List<LDAPModel> ldapModelList = ldapTemplate.search(ldapQuery, (Attributes attrs) ->
LDAPModel.builder()
.userId(getValue(attrs, "userid"))
.telephoneNumber(getValue(attrs, "phoneNumber"))
.build());
return ldapModelList;
}
Then just use your library to return the json array. I suppose you use jackson.
Just make sure in LDAPModel you have
getters and setters
empty constructor if you add your own constructor having params. But if you don't add any constructor, then no need to add this default empty constructor as java will automatically create it for you.
LDAPModel class is as follows:
public class LDAPModel {
String userId;
String telephoneNumber;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getTelephoneNumber() {
return telephoneNumber;
}
public void setTelephoneNumber(String telephoneNumber) {
this.telephoneNumber = telephoneNumber;
}
}
For the object to JSON string conversion using Jackson, I assume you already know it or can find out how.
I am trying to map Json response whose attributes changes if there is any error. For example:
valid response :
{
"Header":[{
//some data
}],
"Component":[{
//data
}],
"ServiceParameter":[{
//data
}]
}
error response:
{
"Header":[{
//some data
}],
"ErrorMessage":[{
//data
}],
"ServiceParameter":[{
//data
}]
}
How can I map(with Jackson if possible) component data or error message for the given response ?
I can only think of having both fields included in your POJO, like this:
class JsonResponse {
#JsonProperty("Headers")
private List<Header> headers;
#JsonProperty("Component")
private List<Component> components;
#JsonProperty("ErrorMessage")
private List<ErrorMessages> errorMessages;
#JsonProperty("ServiceParameters")
private List<ServiceParameters> serviceParameters;
// Getters and setters
}
You can then know whether it's an error or not by checking if the errorMessages list is empty or not.
Jackson is a very flexible JSON (de)serializer, so it's very likely there's a way to do it, but this one is definitely the easiest one!
I have to send a batch of instructions in JSON data format as below:
{
"batchId": "123456",
"instructions": [ {
"instructionId": "1",
"customer": {
"iban": "abc",
"name": "abc"
}
},
"instructionId": "2",
"customer": {
"iban": "abc",
"name": "abc"
}
}
.
.
.
.. . . ..
]
}
Now, i will fetch multiple records/instructions from the database via query, which I will use to generate the JSON data-set as per the format above.
What I have researched: I have traversed many solutions and thought of my own that I shall create an object class of Instruction mapping with setters and getters. I shall use a loop through each record and set values of object fields from database via setter and add entry that complete object entry to JSON via getters.
I will continue this approach until the records are read completely.
My question is: Is this solution efficient and best one to deal with such requirement or any other suggestion?
Please suggest? Any sort of code snippet or help is appreciated.
You can use com.google.gson for that.
Create the Instruction object and then add the fields and annotate the field with SerializedName if you are mapping a different json name to your java field(E.g. instruction_id to instructionId).
import com.google.gson.annotations.SerializedName;
import java.util.List;
import java.util.Map;
public class Instruction {
#SerializedName("instructionId")
private String instructionId;
#SerializedName("customer")
private List<Map<String, Object>> customer;
public String getInstructionId() {
return instructionId;
}
public void setInstructionId(String instructionId) {
this.instructionId = instructionId;
}
public List<Map<String, Object>> getCustomer() {
return customer;
}
public void setCustomer(List<Map<String, Object>> customer) {
this.customer = customer;
}
}
And then you can map your json to your instruction class.
Instruction instruction = new GsonBuilder()
.setPrettyPrinting()
.create()
.fromJson(json, Instruction.class);
JSON
{
"type": {
"type1": {
"sub1": [
"sub1A": {
}
]
}
}
"type2": {
"type1": {
"sub1": [
"sub1A": {
}
]
}
}
}
I have Json like this , I am not getting how to create map for this, like
Map<String, Object> requestMap = new HashMap<>();
requestMap.get("type");
Inside type again create map containing sub data.
I didn't understand your question completely. But, from your statement, if you are trying to fetch json data into your class and that JSON data has recursive mapping, i.e., one object contains itself under its body. Then, I don't think you need HashMap to map this json into your class. You can use single Entity with a field of type of itself like employee-manager relationship. e.g.,
class Type {
private Type type;
private String otherField;
// constructors, setters, getters
}
Now, you can read values from type using the recursive functions.
According to what you have shared you can use:
Map <String, Map<String, Map<String, Set<Map<String, String>>>>>
Or to get more details concerning working with json objects you can look at: Query a JSONObject in java
We want to write an API that looks something like this:
#XmlRootElement(name = "MyData")
#XmlAccessorType(XmlAccessType.FIELD)
public static class MyData {
public String name;
public Map<String,String> data;
}
#GET
#Path("/mydata")
public MyData getMyData() {
MyData ret = new MyData();
ret.name = "map data";
ret.data = new HashMap<>();
ret.data.put("a1", "b1");
ret.data.put("a2", "b2");
return ret;
}
But here's the sticking point we cannot seem to get around: we want this to return a JSON structure something like this:
{
"MyData":{
"name":"map data",
"data":{
"a1": "b1",
"a2": "b2"
}
}
}
and we can't figure out how to get beyond something like
{
"MyData":{
"name":"map data",
"data":{
"entry":[
{
"key":"a1",
"value":"b1"
},
{
"key":"a2",
"value":"b2"
}
]
}
}
}
Any idea how we might do this? I'm pretty sure this can be done, because I once saw a demo of it. We're using tomcat, Java 7, CXF 2.7.3, and Jackson 2.1.2. Two points:
Note that it doesn't have to contain a Map necessarily: all we need is to marsall a bunch of key/values where the keys are not known in advance.
We have to go both directions - we need to implement PUT/POST as well as GET with this syntax in the representation.
If you want to return only JSON (do not support XML), then simply remove all JAXB annotations from MyData and you will get a pretty good structure, but without the wrapping "MyData" element (which seems redundant to me). You could e.g use core Jackson annotations, like #JsonIgnore (instead of JAXB's). If you want to add the root wrapping element, you could set the WRAP_ROOT_VALUE to true.