AWS DynamoDB - save a JSON Array to a table (Java/Android) - java

How do you save a JSON Array as an item attribute? AWS documentation is the absolute worst thing ever - it contradicts itself, a lot of things are either redundant or only partially explained, some things aren't explained at all - I don't know how anyone manages to use it.
Anyway, suppose I have a table called Paths, and a path has a name, an ID, and a list of LatLngs (formatted as a JSON Array)
In the class definition for this table, I have
#DynamoDBTable(tableName = "Paths")
public class Path {
private String id;
private String name;
private JSONArray outlineJSON;
with getters and setters like
#DynamoDBRangeKey(attributeName = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
which works fine for strings, booleans and numbers, and the object saves successfully to the table.
AWS documentation mentions JSON several times, and says it can handle lists, but it doesn't explain how to use lists or give any examples.
I used #DynamoDBHashKey for the id, #DynamoDBRangeKey for name, and #DynamoDBAttribute for other strings, numbers or booleans, and I tried it here
#DynamoDBAttribute(attributeName = "outline")
private JSONArray getOutlineJSON() {
return outlineJSON;
}
private void setOutlineJSON(JSONArray outlineJSON) {
this.outlineJSON = outlineJSON;
}
It successfully saved the object but without the array.
How do I save the array? I can't find an explanation anywhere. I think #DynamoDBDocument might have something to do with it, but all the documentation on the subject gives unrelated examples, and I can't find any using a list like my in situation.
EDIT: For now, I have a working solution - I can easily convert my lists to JSONArrays and then convert those to Strings, and vice-versa.

You can define your class to be something like
#DynamoDBTable(tableName = "Paths")
public class Path {
private String id;
private String name;
private LatLang latLangs;
#DynamoDBHashKey(attributeName="id")
public String getId() { return id;}
public void setId(String id) {this.id = id;}
#DynamoDBRangeKey(attributeName = "name")
public String getName() { return name; }
public void setName(String name) { this.name = name; }
#DynamoDBDocument
public static class LatLang{
public String lat;
public String lang;
}
}

Related

Jackson: remove some values from json and keep some null values

I have a model like this:
public class Employee {
#JsonProperty("emplyee_id")
private Integer id;
#JsonProperty("emplyee_first_name")
private String firstName;
#JsonProperty("emplyee_last_name")
private String lastName;
#JsonProperty("emplyee_address")
private String address;
#JsonProperty("emplyee_age")
private Byte age;
#JsonProperty("emplyee_level")
private Byte level;
//getters and setters
}
now I need to create two JSONs using this (only) model.
the first one must like this for example:
{
"employee_id":101,
"employee_first_name":"Alex",
"employee_last_name":"Light",
"employee_age":null,
"employee_address":null
}
and the second one must like this for example:
{
"employee_id":101,
"employee_level":5
}
by the way, I already tested #JsonIgnore and #JsonInclude(JsonInclude.Include.NON_NULL).
the problem of the first one (as much as I know) is, those fields can't be included in other JSONs (for example if level get this annotation, it won't be included in the second JSON)
and the problem of the second one is, null values can't be included in JSON.
so can I keep null values and prevent some other property to be included in JSON without creating extra models? if the answer is yes, so how can I do it? if it's not I really appreciate if anyone gives me the best solution for this state.
thanks very much.
it could be useful for you using #JsonView annotation
public class Views {
public static class Public {
}
public static class Base {
}
}
public class Employee {
#JsonProperty("emplyee_id")
#JsonView({View.Public.class,View.Base.class})
private Integer id;
#JsonProperty("emplyee_first_name")
#JsonView(View.Public.class)
private String firstName;
#JsonProperty("emplyee_last_name")
#JsonView(View.Public.class)
private String lastName;
#JsonProperty("emplyee_address")
private String address;
#JsonProperty("emplyee_age")
private Byte age;
#JsonProperty("emplyee_level")
#JsonView(View.Base.class)
private Byte level;
//getters and setters
}
in your json response add #JsonView(Public/Base.class) it will return based on jsonview annotations
//requestmapping
#JsonView(View.Public.class)
public ResponseEntity<Employee> getEmployeeWithPublicView(){
//do something
}
response:
{
"employee_id":101,
"employee_first_name":"Alex",
"employee_last_name":"Light",
"employee_age":null,
"employee_address":null
}
for the second one
//requestmapping
#JsonView(View.Base.class)
public ResponseEntity<Employee> getEmployeeWithBaseView(){
//do something
}
response
{
"employee_id":101,
"employee_level":5
}

Jackson JSON Mapping JSON keys with JAVA BEAN

I'm using Jackson JSON LIB 2.8, and i'm using Json.mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES,true);
but sometimes I need to map some fields with two differents names like
POJO has attribute builindg and i need to map it to buildingUid or BUILDING depends on what key exist in JSON, are they any way to do this ?
Example :
public class Building extends Bean {
private UUID id;
private String name;
}
and I have two different sources , one is my Database which return a JSON with this format :
{
"ID":"build",
"NAME":"name1"
}
and my other source is a client :
{
"UID" : "build",
"name" : "name1"
}
As you can see my problem is to map id with both UID and ID , i manage to map the first one with :
Json.mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES,true);
but the other source is UID and i dont know how to map it automatically when i do something like
Json.encode(Building.toString());
It is possible using multiple setters annotated with #JsonSetter
Try something like this :
public class Building extends Bean {
private String id;
private String name;
#JsonGetter("id")
public String getId() {
return id;
}
#JsonSetter("id")
public void setId(String id) {
this.id = id;
}
#JsonSetter("UID")
public void setUID(String id) {
setId(id);
}
#JsonGetter("name")
public String getName() {
return name;
}
#JsonSetter("name")
public void setName(String name) {
this.name = name;
}
#JsonSetter("NAME")
public void setUpperCaseName(String name) {
setName(name);
}
}
But it's a little lousy (solution not dynamic).

Constructor annotated with Jackson #JsonCreator not being called in POJO?

I am working with a web service that stores POJOs in a MongoDB. I want to make use of Mongo's 'expireAfterSeconds' time to live feature, to clear out old documents in my collection after a certain period of time.
Initially I had an implementation that sent the date to the REST service using the following JSON:
{
"testIndex": "testIndex",
"name": "hello",
"date": "2016-05-09T11:00:39.639Z"
}
The above code created the document in the collection, and with the following annotation, deleted the document after 10 seconds.
#Indexed (expireAfterSeconds=10)
private Date date;
After implementing this code, I decided I wanted to generate the date only on the Java side, meaning the JSON is now as follows:
{
"testIndex": "testIndex",
"name": "hello"
}
Then I have a constructor in the POJO using JsonCreator from Jackson
#JsonCreator
public TTLTestVO (#JsonProperty("testIndex") String testIndex, #JsonProperty("name") String name) {
this.testIndex = testIndex;
this.createdAt = new Date();
this.name = name;
}
From reading the documentation here I believe this should flag the constructor to be used when creating a new object. The testIndex and name fields are populated as before. However with this implementation, each time I check the document in my mongo the date value is 'null'. If I change the text for one of the string values to 'hello from the constructor', the constructor appears not to be called as the initial text contained in the JSON is what is added to the database.
POJO
`
#Document(collection = "test")public class TTLTestVO {
#Id private String _id;
#Indexed
private String testIndex;
#Indexed (expireAfterSeconds=10)
private Date createdAt;
private String name;
#JsonIgnore
public TTLTestVO() {
// default
}
#JsonCreator
public TTLTestVO (#JsonProperty("testIndex") String testIndex, #JsonProperty("name") String name) {
this.testIndex = "hello from the constructor";
this.name = name;
}
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 getTestIndex() {
return testIndex;
}
public void setTestIndex(String testIndex) {
this.testIndex = testIndex;
}
public Date getDate() {
return createdAt;
}
public void setDate(Date date) {
this.createdAt = date;
}
`
After investigating some more I discovered the issue lies with the Spring Framework implementation of #JsonCreator - I removed the imports for org.springframework.cloud.cloudfoundry.com.fasterxml.jackson.annotation and replaced them with com.fasterxml.jackson.annotation. The above implementation now functions as expected.
I have been unable to find an explanation online as to why the spring version isn't working, so if anyone has any ideas please let me/ others know

Lambda in Java - Could not analyze lambda code

I’ve got an application with Hibernate (JPA) which I am using in combination with Jinq. I’ve got a table which lists entities and I want the user to be able to filter it. In the table there are persons listed.
#Entity
public class Person {
private String firstName;
private String surName;
#Id
private int id;
public Person() {
}
public Person(final String pFirstName, final String pSurName, final int pID) {
firstName = pFirstName;
surName = pSurName;
id = pID;
}
public int getId() {
return id;
}
public void setId(final int pID) {
id = pID;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(final String pFirstName) {
return firstName = pFirstName;
}
public String getSurName() {
return surName;
}
public void setSurName(final String pSurName) {
surName = pSurName;
}
}
I am using JavaFX for this, but this shouldn’t matter. First thing I tried was to filter the persons by their surname. For filtering, I used Jinq in combination with lambda. My filtering code looks like this:
private List<Person> getFilteredPersons(final String pSurName){
JPAJinqStream<Person> stream = streamProvider.streamAll(Person.class);
stream.where(person -> person.getSurName().contains(pSurName));
List<Person> filteredList = stream.toList();
stream.close();
return filteredList;
}
So the object I am operating on is a normal String. I don’t think that my Person class has anything to do with that. My first thought was, that you can’t use the method boolean contains(...) in lambda because when the error showed up, it said:
Caused by: java.lang.IllegalArgumentException: Could not analyze lambda code
So my question is, is it somehow possible to use the contains-method of a String in lambdacode?
Your question has nothing to do with JPA or lambdas, but everything to do with jinq: it simply doesn't support translating String.contains() to a database query. See http://www.jinq.org/docs/queries.html#N65890 for what is supported.

Convert Userdefined Object to a String Object

I have a user defined class, say
import java.util.Calendar;
public class Employee{
private String name;
private int age;
private Calendar dob;
private Address address;
private boolean married;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Calendar getDob() {
return dob;
}
public void setDob(Calendar dob) {
this.dob = dob;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public boolean isMarried() {
return married;
}
public void setMarried(boolean married) {
this.married = married;
}
}
class Address{
private int doorNo;
private String streetName;
private String city;
public int getDoorNo() {
return doorNo;
}
public void setDoorNo(int doorNo) {
this.doorNo = doorNo;
}
public String getStreetName() {
return streetName;
}
public void setStreetName(String streetName) {
this.streetName = streetName;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
I am creating an object of Employee and populating it with setters. I have to represent the above object to string (encrypted or human-readable) and parse back to get similar object. Actually, I want to save the string equivalent of java object in a file and to read back them to get a java object. I know we have object writing, but they are sensitive to edit. I would prefer if a java object can be converted to String of human readable form. Thanks.
To keep your flattened object human readable and hand editable consider encoding your object into a JSON string using one of the popular JSON libraries. Same JSON library will also provide you APIs to decode a JSON string into your object.
One of the popular JSON library is Gson. Here's an use example: Converting JSON to Java
You should override toString() to convert instances of your class to string. As for recreating instances based on their string representation you can define a static factory method for this.
public class Employee {
...
#Override
public String toString() {
...
}
public static Employee fromString(String str) {
...
}
}
You use these methods like this:
To obtain string representation of an instance to string:
Employee john = ...
String johnString = john.toString();
Note that your toString() method will also be called implicitly whenever there is a need to obtain string representation of one of the instances.
To recreate an instance from string:
Employee john = Employee.fromString(johnString);
If you often need to store instances of the class in a file and read them back, you may also consider serialization. See documentation for Serializable interface as well as ObjectInputStream and ObjectOutputStream. You may also want to familiarize yourself with caveats surrounding serialization by reading the last chapter ("Serialization") in Effective Java, second edition. Most importantly be aware that the serialized form of your class becomes part of your public API.
You might be looking for the toString method:
Returns a string representation of the object. In general, the
toString method returns a string that "textually represents" this
object. The result should be a concise but informative representation
that is easy for a person to read. It is recommended that all
subclasses override this method.
In your case you would be doing something of the sort (to be added in each of your classes):
#Override
public String toString()
{
return "Name = " + name + ...
}
The string can be of any format you wish. To save the object, all that you need to do is to write the text that the toString method returns to a file.
To read them back, however, you will have to implement your own logic. On the other hand, what you can do, is to use something such as XStream (instructions here) which will automatically convert your object to XML.
XML is human readable so that your users can modify whatever they need. Once this is done, you can re-use XStream to read back your object.
Try this
Employee em = new Employee;
//Your code
str obj= JavaScriptSerializer.Serialize();
// whenever you want to get object again
Employee emp = (Employee)JavaScriptSerializer.Deserialize();

Categories