I have these messages arriving from SQS:
{
"eventID": "zzz",
"eventName": "MODIFY",
"eventVersion": "1.1",
"eventSource": "aws:dynamodb",
"awsRegion": "us-east-1",
"dynamodb": {
"ApproximateCreationDateTime": 1521976320,
"Keys": {
"key_1": {
"S": "yyy"
},
"key_2": {
"S": "xxx"
}
},
"SequenceNumber": "123",
"SizeBytes": 321,
"StreamViewType": "KEYS_ONLY"
},
"eventSourceARN": "arn:aws:dynamodb:us-east-1:eventSourceARN",
"itemType": "myItem"
}
I want to use gson library to convert this json string into a Record object (com.amazonaws.services.dynamodbv2.model.Record) which contains a StreamRecord object (com.amazonaws.services.dynamodbv2.model.StreamRecord) that represents the dynamodb sub json.
problem is that the inner fields of the dynamodb object are PascalCase while the other fields are normal camelCase.
This code:
Gson gson = new GsonBuilder()
//.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
.create();
String json = <the json from the example above>
Record record = gson.fromJson(json, Record.class);
log.info("record="+record.toString());
StreamRecord dynamodb = record.getDynamodb();
log.info("dynamodb="+dynamodb.toString());
Map<String, AttributeValue> keys = dynamodb.getKeys();
log.info("keys="+keys.toString());
prints this log (UPPER_CAMEL_CASE commented out) :
record={EventID: zzz,EventName: MODIFY,EventVersion: 1.1,EventSource: aws:dynamodb,AwsRegion: us-east-1,Dynamodb: {},}
and then throws Null Pointer exception because the dynamoDb object is empty - because my json string is UPPER_CAMEL_CASE, while in the object its normal camelCase.
I want to apply FieldNamingPolicy.UPPER_CAMEL_CASE only for the dynamodb sub json.
perhaps somehow using FieldNamingStrategy ?
The json is given and I cannot change its schema.
I also can't change the fact that I get it as string.
see AWS API:
https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_streams_Record.html
https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_streams_StreamRecord.html
You seem to want the following naming strategy:
private static final Gson gson = new GsonBuilder()
.setFieldNamingStrategy(field -> {
if ( field.getDeclaringClass() == StreamRecord.class ) {
return FieldNamingPolicy.UPPER_CAMEL_CASE.translateName(field);
}
return FieldNamingPolicy.IDENTITY.translateName(field);
})
.create();
I usually never use naming strategies in favor of the #SerializedName annotation though, just to be more precise when declaring mappings.
Related
I am trying to consume a json through an api using Google's GSON library to be able to recover the data.
I would like to be able to obtain the data of the CssValidation and Result key but it took hours and I have not been able to get it.
{
"cssvalidation": {
"uri": "https://www.mywebsite.com",
"checkedby": "http://www.w3.org/2005/07/css-validator",
"csslevel": "css3",
"date": "2021-10-17T05:07:38Z",
"timestamp": "1634490458519",
"validity": false,
"result": {
"errorcount": 7,
"warningcount": 350
}
}
}
My code in java is this:
Gson gson = new Gson();
ApiResponse apiResponse = gson.fromJson(response.body().string(), ApiResponse.class);
public class ApiResponse {
private CssValidation validation;
}
public class CssValidation{
public String uri;
public String getUri() {
return uri;
}
}
There are some problems with your json string which you need to fix before attempting to parse it, the uri value quotation is not closed, and there is an additional comma after the result object, after fixing both you end up with the functional json text
{
"cssvalidation": {
"uri": "https://www.mywebsite.com",
"checkedby": "http://www.w3.org/2005/07/css-validator",
"csslevel": "css3",
"date": "2021-10-17T05:07:38Z",
"timestamp": "1634490458519",
"validity": false,
"result": {
"errorcount": 7,
"warningcount": 350
}
}
}
you can parse it with the JsonParser and get its elements in the following way
JsonObject root = JsonParser.parseString(resp).getAsJsonObject();
JsonObject cssValidation = root.get("cssvalidation").getAsJsonObject();
String uri = cssValidation.get("uri").getAsString();
System.out.println(uri);
And you will get the following output
https://www.mywebsite.com
You seem to be doing it right, but your Java object property keys need to match up exactly with the keys in the JSON.
Specifically, the name of the property validation needs to changed to cssvalidation, so like this:
Gson gson = new Gson();
ApiResponse apiResponse = gson.fromJson(response.body().string(), ApiResponse.class);
public class ApiResponse {
private CssValidation cssvalidation;
}
public class CssValidation{
public String uri;
public String getUri() {
return uri;
}
}
Also, if the given JSON string is really what you get, then your JSON needs to be fixed, as pointed out by Lukas Ownen's answer
I have the following JSON structure:
{
"uri": {
"{{firstname}}": "Peter",
"{{lastname}}": "Griffin",
"{{age}}": 42
}
}
I want to deserialize it into my Bean:
public class Uri {
private String firstname;
private String lastname;
private int age;
/* getter and setter */
}
But I get the following error:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "uri" (class com.abc.Uri), not marked as ignorable (3 known properties: "firstname", "lastname", "age")
So I assume, I need to get into the property uri.
Is there any way, to start parsing directly within the uri property?
Update:
This is how I read the JSON:
ObjectMapper mapper = new ObjectMapper();
uri = mapper.readValue(new URL("test2.json"), Uri.class);
Your method will not work because you are trying to get the whole json object at once, without getting a specific node at first.
Instead of loading your json with the mapper constructor, get your json in a different way. I would use URL and HTTPURLConnection to get the json string from the web.
After you have your json string, use this:
ObjectMapper objectMapper = new ObjectMapper();
JsonNode rootNode = objectMapper.readTree(json);
Get the json node that uri represents, like this:
JsonNode uriNode = rootNode.get("uri");
And only then send that node to be parsed, like this:
Jackson 2.4
Uri uri = objectMapper.treeToValue(uriNode, Uri.class);
Prior to Jackson 2.4
Uri uri = objectMapper.readValue(uriNode, Uri.class);
You JSON should be of the format:
{
"uri": {
"firstname": "Peter",
"lastname": "Griffin",
"age": 42,
}
}
[
{
"updated_at":"2012-03-02 21:06:01",
"fetched_at":"2012-03-02 21:28:37.728840",
"description":null,
"language":null,
"title":"JOHN",
"url":"http://rus.JOHN.JOHN/rss.php",
"icon_url":null,
"logo_url":null,
"id":"4f4791da203d0c2d76000035",
"modified":"2012-03-02 23:28:58.840076"
},
{
"updated_at":"2012-03-02 14:07:44",
"fetched_at":"2012-03-02 21:28:37.033108",
"description":null,
"language":null,
"title":"PETER",
"url":"http://PETER.PETER.lv/rss.php",
"icon_url":null,
"logo_url":null,
"id":"4f476f61203d0c2d89000253",
"modified":"2012-03-02 23:28:57.928001"
}
]
First create one class (Json_obj) for your json data.Then you can try this :
String json_str='[ { "updated_at":"2012-03-02 21:06:01", "fetched_at":"2012-03-02 21:28:37.728840", "description":null, "language":null, "title":"JOHN", "url":"http://rus.JOHN.JOHN/rss.php", "icon_url":null, "logo_url":null, "id":"4f4791da203d0c2d76000035", "modified":"2012-03-02 23:28:58.840076" }, { "updated_at":"2012-03-02 14:07:44", "fetched_at":"2012-03-02 21:28:37.033108", "description":null, "language":null, "title":"PETER", "url":"http://PETER.PETER.lv/rss.php", "icon_url":null, "logo_url":null, "id":"4f476f61203d0c2d89000253", "modified":"2012-03-02 23:28:57.928001" } ]';
Gson gson = new Gson();
Json_obj json_obj = gson.fromJson(json_str, Json_obj.class);
Now your json data is converted in an object.You can fetch any value from that object.
I suggest you just use jackson library instead.
You can just quickly have
ObjectMapper mapper = new ObjectMapper () // this reads json to Pojo and writes Pojo to json
YourPojoClass obj = mapper.readValue (....)
Reference: mkyong.com/java/jackson-2-convert-java-object-to-from-json
I want to deserialize a json like this
{
"0":{"name":"Alice"},
"1":{"name":"Bob"}
}
to a java collection( set or list, not map).
I want to change the default behavior of CollectionDeserializer to support this and config it as a global configuration. Any way to to this?
If you really have this structure (an object as a container and not an array, which could be handled much easier):
import com.fasterxml.jackson.databind.*;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
public class Main {
public static void main(String[] args) throws IOException {
String json = "{\"0\":{\"name\":\"Alice\"}, \"1\":{\"name\":\"Bob\"}}";
ObjectMapper mapper = new ObjectMapper();
JsonNode obj = mapper.readValue(json, JsonNode.class);
Iterator<Map.Entry<String, JsonNode>> userEntries = obj.fields();
while(userEntries.hasNext()){
Map.Entry<String, JsonNode> userEntry = userEntries.next();
System.out.println(userEntry.getKey() + " => " + userEntry.getValue());
}
}
}
You can achieve this task using gson api.
The code is as follows:
String yourJson = "{\"0\":{\"name\":\"Alice\"}, \"1\":{\"name\":\"Bob\"}}";
Gson gson = new Gson();
Type tarType = new TypeToken<Map<String,Map<String,String>>>(){
}.getType();
gson.fromJson(yourJson, tarType);
For this you need to add following:
com.google.gson.Gson
Why not to turn your JSON document into an array as:
{"persons":[{"name":"Alice"},{"name":"Bob"}]}
Then define a corresponding JSON schema (assuming PersonArray is the file name):
{
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "Some description",
"type" : "object",
"properties" : {
"persons" : {
"type" : "array",
"items" : { "$ref": "#/definitions/person" }
}
},
"definitions": {
"person" : {
"type": "object",
"description": "A person",
"properties": {
"name": { "type": "string" }
}
}
}
}
and take advantage of Jackson Data Binding API by using jsonschema2pojo-maven-plugin Maven plugin to generate POJOs in Java (alternatively, you can manually implement POJOs).
Once POJOs are generated, you can use ObjectMapper to deserialise JSON document in the following way:
ObjectMapper mapper = new ObjectMapper();
PersonArray personArray = mapper.readValue(serialisedJsonDocument, PersonArray.class);
The elements of your JSON document will be stored inside PersonArray object as:
List<Person> persons = new ArrayList<Person>();
You could also add additional properties to the Person object if you needed.
I'm getting this error when I receive only one single item in a list. I'm using Jersey in the server side REST Web service, I only get the error when the List returned one single element and when it has 0 elements I get java.lang.NullPointerException But when it has more than one it works perfectly, and this is how I'm doing it :
#GET
#Path("getproject")
#Produces(MediaType.APPLICATION_JSON)
public List<Project> getPagedProjects(
#QueryParam("offset") int offset,
#QueryParam("limit") int limit,
#QueryParam("searchKey") String searchKey) throws Exception {
System.out.println("Returning Paged Project ");
return projectService.getPagedProjects(offset, limit, searchKey);
}
Why doesn't Jersey send a list that contains one single item? It is a bug in jersey?
Is there a way to make it always serialize as an array?
This is my JSON data when the web service returns 0 element:
null
And This is my JSON data when web service returns 1 element :
{
"project": {
"abbreviation": "abc",
"customer": "customer1",
"description": "description3",
"icon": "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",
"name": "projectname3",
"plannedEndDate": "2012-05-23T00:00:00+01:00",
"plannedStartDate": "2012-05-23T00:00:00+01:00",
"projectStatus": {
"name": "In Progress"
},
"realEndDate": "2012-05-23T00:00:00+01:00",
"realStartDate": "2012-05-23T00:00:00+01:00"
}
}
And This is my JSON data when web service returns more than 1 element :
{
"project": [
{
"abbreviation": "abd",
"customer": "customer1",
"description": "description1",
"icon": "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",
"name": "projectname1",
"plannedEndDate": "2012-05-25T00:00:00+01:00",
"plannedStartDate": "2012-05-23T00:00:00+01:00",
"projectStatus": {
"name": "Opened"
},
"realEndDate": "2012-05-25T00:00:00+01:00",
"realStartDate": "2012-05-23T00:00:00+01:00"
},
{
"abbreviation": "bd",
"customer": "customer1",
"description": "description2",
"icon": "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",
"name": "projectname2",
"plannedEndDate": "2012-05-23T00:00:00+01:00",
"plannedStartDate": "2012-05-23T00:00:00+01:00",
"projectStatus": {
"name": "Closed"
},
"realEndDate": "2012-05-23T00:00:00+01:00",
"realStartDate": "2012-05-23T00:00:00+01:00"
},
{
"abbreviation": "abc",
"customer": "customer1",
"description": "description3",
"icon": "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",
"name": "projectname3",
"plannedEndDate": "2012-05-23T00:00:00+01:00",
"plannedStartDate": "2012-05-23T00:00:00+01:00",
"projectStatus": {
"name": "In Progress"
},
"realEndDate": "2012-05-23T00:00:00+01:00",
"realStartDate": "2012-05-23T00:00:00+01:00"
}
]
}
And in android side I deserialize the JSON response like this :
Gson gson = new Gson();
final ProjectContainer container = gson.fromJson(resultat, ProjectContainer.class);
final ListView lv = (ListView) findViewById(R.id.list);
adaptateur = new ProjectAdapter(ProjectActivity.this, R.layout.ligne_project, container);
lv.setAdapter(adaptateur);
This is my ProjectContainer class :
public class ProjectContainer {
#SerializedName("project")
List<Project> projects ;
public List<Project> getProjects() {
return projects;
}
public void setProjects(List<Project> projects) {
this.projects = projects;
}
}
I would greatly appreciate your help to solve this problem. Thanks in advance
Your issue results really weird for me... it seems that there must be some problem with Jersey's JSON serialization of single element arrays... if you Google "Jersey JSON single element arrays" you'll find the same issue, like here or here. I don't know too much about Jersey, so I can't help you with that...
That said, I can suggest a workaround using manually parsing in Gson, to adapt your parsing to the 2 different responses (object or array). You could do something like this:
//manually parsing until get the "project" element...
JsonParser parser = new JsonParser();
JsonObject rootObejct = parser.parse(yourJsonString).getAsJsonObject();
JsonElement projectElement = rootObejct.get("project");
Gson gson = new Gson();
List<Project> projectList = new ArrayList<>();
//Check if "project" element is an array or an object and parse accordingly...
if (projectElement.isJsonObject()) {
//The returned list has only 1 element
Project project = gson.fromJson(projectElement, Project.class);
projectList.add(project);
}
else if (projectElement.isJsonArray()) {
//The returned list has >1 elements
Type projectListType = new TypeToken<List<Project>>() {}.getType();
projectList = gson.fromJson(projectElement, projectListType);
}
//Now you have a List<Project> projectList with one or many Project elements,
//depending on the response...
Note that you don't need your class ProjectContainer.
Something like this should work for you, although obviously the best thing would be fix the serialization issue!
Basically, your web service is broken in terms of how it's replying. If there's only one object for project it's returning only an object instead of an array.
MikO's answer solves the problem but another approach is encapsulating that logic in a custom deserializer:
class MyDeserializer implements JsonDeserializer<ProjectContainer> {
#Override
public ProjectContainer deserialize(JsonElement je, Type type, JsonDeserializationContext jdc) throws JsonParseException {
JsonObject jo = je.getAsJsonObject().getAsJsonObject("project");
if (jo.isJsonArray()) {
return new Gson().fromJson(je, ProjectContainer.class);
} else {
Project p = jdc.deserialize(jo, Project.class);
List<Project> pList = new ArrayList<Project>(1);
pList.add(p);
ProjectContainer pc = new ProjectContainer();
pc.setProjects(pList);
return pc;
}
}
}
Then you can use:
Gson gson = new GsonBuilder()
.registerTypeAdapter(ProjectContainer.class, new MyDeserializer())
.build();
ProjectContainer pContainer = gson.fromJson(myJson, ProjectContainer.class);
I ended up using Jackson library instead of gson to parse the json response. It automatically converts object into ArrayList. It is pretty much similar to gson in terms of ease of use. Hope it helps!