I have a node.js application with an Angular Webfrontend and an Android App connecting to the backend via rest. Now I'm not sure how to return objects from node to the clients:
Way 1:
res.send(req.user);
If I'll do it like this I can load the user object from angular like:
return $http.post('/api/login', user)
.success(function (data) {
$rootScope.currentUser = data;
and in my Android app (simplyfied call, I use Spring and Gson):
user = SpringRestTemplate.getRestTemplate().postForObject(Routes.getLogin(), user, User.class);
This works fine, but what I actually would like to return from node would be my
Way 2:
res.send({user: req.user });
for angular everything pretty much stays the same:
$rootScope.currentUser = data.user;
but for android I didn't found any other way than to write the json conversion myself:
ResponseEntity<Map> map = SpringRestTemplate.getRestTemplate().postForEntity(Routes.getLogin(), dUser, Map.class);
LinkedTreeMap<String, User> map2 = (LinkedTreeMap<String, User>) map.getBody();
Map ltm = (Map) map.get("user");
String id = (String) ltm.get("_id");
String userName = (String) ltm.get("userName");
// ... and so on
I get, why this is the case (except why I had to use a second map), but I wonder if there's any simplier way to achieve my second way.
I left the Models and the SpringRestTemplate Code out, since this is more a general question on how to handle JSON with the following structure:
{ user : { _id: "1", userName: "foo", ...}}
Any guidance on how to deal with this problem would be much appreciated!
This is simplified, but this will solve your issue.
Create a POJO that matches the JSON Schema using Json Schema to POJO
If you can, use Retrofit or something more easily suited for Android to consume the API.
Create a retrofit service (look at the retrofit link above) and then connect to the API and you'll have a User object.
Option B:
Use GSON to deserialize your object into a POJO from your spring stuff. But I recommend using Retrofit or something similar as its easier and cleaner.
Related
I am trying to parse the results of an API call which returns a unique first property.
{
"AlwaysDifferent12345": {
"fixedname1" : "ABC1",
"fixedname2" : "ABC2"
}
}
I am using retrofit2 and jackson/gson and cannot figure out how to cope with dynamic property names within the retrofit2 framework. The following works fine
data class AlwaysDifferentDTO(
#JsonProperty("AlwaysDifferent12345") val alwaysDifferentEntry: AlwaysDifferentEntry
)
I have tried
data class AlwaysDifferentDTO(
#JsonProperty
val response: Map<String, AlwaysDifferentEntry>
)
But this returns errors Can not instantiate value of type... The return value from the API is fixed i.e. map<string, object>.
I have read you can write a deserializer but it looks like I need to deserialize the whole object when all I want to do is just ignore the string associated with the response.
I have read
https://discuss.kotlinlang.org/t/set-dynamic-serializedname-annotation-for-gson-data-class/14758
and several other answers. Given unique properties names are quite common it would be nice to understand how people deal with this when using retrofit2
Thanks
Because the JSON doesn't have a 1-to-1 mapping Jackson can't map it automatically using annotations. You are going to need to make your own Deserializer.
In this tutorial you can learn how to create your own custom Deserializer for Jackson. https://www.baeldung.com/jackson-deserialization
In the tutorial you will see the first line under the deserialize function is
JsonNode node = jp.getCodec().readTree(jp);
using this line you can get the JSON node as a whole and once you have it you can call this function
JsonNode AlwaysDifferent12345Node = node.findParent("fixedname1");
Now that you have that node you can retrieve its value like shown in the rest of the tutorial. Once you have all the values you can return a new instance of the AlwaysDifferentDTO data class.
First I know my title is bad as I didn't come up with better, I'm opened to suggestion.
I'm using retrofit to get data from an api of this kind : #GET("users/{userid}")
It works fine and I'm happy with it, the problem is when I call the same api with #POST("users/widget") with a list of ids. I have the following answer :
{
"long_hash_id": {
"_id": "long_hash_id"
.......
},
"long_hash_id": {
"_id": "long_hash_id",
.....
},
........
}
the "long_hash_id" is typicaly "525558cf8ecd651095af7954"
it correspond to the id of the user attached to it.
When I didn't use retrofit, I used Gson in stream mode to get each user one by one. But I don't know how to tell retrofit.
Hope I'm clear and
Thank you in advance.
----------- Solution :
I made my interface this way :
#FormUrlEncoded
#POST(AppConstants.ROUTE_USER_GROUP)
Call<Map<String,User>> getUsers( #Field("ids") List<String> param, #QueryMap Map<String,String> options);
and I simply gave my ArrayList of ids. Thank you very much
Gson is able to deal with JSON objects with variable keys like the one you posted. What you have to do, in this case, is to declare a Map<String, ModelClass>, where ModelClass is the content of the JSONObject you want to represent
To serve a backend for an Android App i am using Google App Engine together with Objectify (4.0.3b).
On the backend I have a simple User Entity, which has a list of Users (friends) as relationship.
#Entity
public class User {
#Id
private String email;
#Load
private List<Ref<User>> friends = new ArrayList<Ref<User>>();
private User() {
}
public List<User> getFriends() {
ArrayList<User> friendList = new ArrayList<User>();
for (Ref<User> ref : this.friends) {
friendList.add(ref.get());
}
return friendList;
}
public void setFriends(List<User> friends) {
List<Ref<User>> refs = new ArrayList<Ref<User>>();
for (User user : friends) {
refs.add(Ref.create(user));
}
this.friends = refs;
}
}
Now when I have following Users stored in the Database for instance : user1 and user2:
user1 has user2 in his friend list and vice versa
When trying to fetch a User object (that has the above cycle reference) from my Endpoint, the Android client throws the following exception:
com.google.appengine.repackaged.org.codehaus.jackson.map.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: java.util.ArrayList[0]...
In this post Infinite Recursion with Jackson JSON and Hibernate JPA issue they recommend to use #JsonIgnore on the field or the getter/setter method.
But on the client side i need to access the friends list by these getter/setter methods (from the generated client library object), so this doesn't help me.
Another tip is to use #JsonManagedReference and #JsonBackReference, which in my case can't be applied since ManagedReference and BackReference would pointto the same friends field.
What I think could solve my Problem is the #JsonIdentityInfo Annotation which is available since Jackson 2.0.
My problem now is that I don't know how I can use this Annotation with Google App Engine.
GAE uses jackson-core-asl-1.9.11, which unfortunately does not have the #JsonIdentityInfo, as it obviously is depending on a version below 2.0.
Does anybody know, how I can use the latest Jackson Version (2.4) in Google App Engine to use the #JsonIdentityInfo feature?
Or is there a better approach for my problem?
The best approach would be to define a DTO class to use as a return parameter for your endpoint and use that to flatten the JSON response (meaning not sending the infinite loop of friend's friends).
We are building a project using couchbase. On Android, I use couchbase lite. Usually, I've been working with relational databases and because I am new to couchbase I am having trouble finding the "correct" architecture. I do understand the core concepts I think, but all the samples and guides seem to stick to some kind of easy setup where they access the database right in the Activities.
I am more used to having some database abstraction where the business logic only get's to see POJO DTO's that are delivered through a database interface or some DAO or something. So I've now annotated my model classes and started writing a simple OR mapper, but with different types of data, foreign keys etc. this is getting quite time consuming quite fast.
Am I completely missing the point here somehow? I can't imagine everyone doing it this way? I everyone writing methods that convert Documents to POJO model classes for each class seperately? Or using a json parser to do that (But that won't work for foreign keys if I wan't to load them too, does it)?
Sorry for the load of questions, but I feel I am missing something obvious here. Thanks!
Will try answering your questions:
Am I completely missing the point here somehow?
No. You can treat noSQL CB as a persistent distributed object cache. So its not RDBMS. However, DAO pattern perfectly fits into this model...since you are dealing with DTOs/ValueObjects/POJOs on DAO level and on noSQL level.
I can't imagine everyone doing it this way?
I suggest write one universal Couchbase manager class that can persist/retrieve a POJO. Then you can re-use it in your DAOs.
Everyone writing methods that convert Documents to POJO model classes
for each class separately? Or using a json parser to do that (But that
won't work for foreign keys if I wan't to load them too, does it)?
You can have one common code in your Couchbase manager class that does conversion from/to json to POJO. So you work with only POJOs and don't see any json in your application code (outside of Couchbase manager class)
Here is an example of such class:
public class CouchbaseManager<K, V>
{
private final Class<V> valueTypeParameterClass;
#Inject
private CouchbaseClient cbClient;
#Inject
private Gson gson;
public CouchbaseManager(final Class<V> valueClass)
{
this.valueTypeParameterClass = valueClass;
}
public V get(K key)
{
V res = null;
String jsonValue = null;
if (key != null)
{
jsonValue = (String) cbClient.get(key);
if (jsonValue != null)
{
res = gson.fromJson(jsonValue, valueTypeParameterClass);
}
}
return res;
}
public void put(K key, V value)
{
int ttl = 0;
cbClient.set(key, ttl, gson.toJson(value, valueTypeParameterClass));
}
}
Then in your DAO code you create instance of CouchbaseManager for each type:
CouchbaseManager<String,Customer> cbmCustomer = new CouchbaseManager<String,Customer>(Customer.class);
CouchbaseManager<String,Account> cbmAccount = new CouchbaseManager<String,Account>(Account.class);
// and so on for other POJOs you have.
// then get/put operations look simple
Customer cust = cbmCustomer.get("cust-1234");
cust.setName("New Name"); // mutate value
// store changes
cbmCustomer.put(cust.getId(), cust);
Now regarding "foreign keys". Remember its not RDBMS so its up to your code to have notion of a "foreign key". For example a Customer class can have an id of an account:
Customer cust = cbmCustomer.get("cust-1234");
String accId = cust.getAccountId();
//You can load account
Account acc = cbmAccount.get(accId);
So as you can see you are doing it all yourself. I wish it was JPA or JDO implementation/provider for Couchbase (like DataNucleus or Hibernate)
You should really start with your POJO/Document design to try to split your POJO entities into "chunks" of data to get a right balance between coarse vs fine grained POJOs.
Also see this discussion on key/document design considerations.
I've been searching for the past week on how to develop an android project, read some on android developers page and on other websites like here, but no text was complete.
i have this project - i'm a php developer not a java, but could understand a bit about java lately.
the thing is i want to develop an android app using my website, i did output a json type data from my website, and gonna use them on the android app, i did the async request on android and could read the data form the website but :
first question: how to parse the json data correctly and convert it to array on android, i did that through:
Iterator<String> itr = myObject.keys();
while (itr.hasNext()) {
...
i don't know if that's the correct way, when i try to convert my json object to array, it gives me type mismatch.
second and more importantly:
how can create a "Block" like facebook posts style, or twitter style blocks, you know - blocks of json data, is it a linearlayout ? what do i call it ? and how can i add it to the UI dynamically, cuz these blocks are pulled from the website json data. so they are arrays...of blocks..
i'm kinda confused still, i need a start point.
Thank you!
excellent tutorial for beginners for android development
http://thenewboston.org/list.php?cat=6
and for your first question - how to parse json data correctly,
you can try using gson to convert the json data into POJO
otherwise you'd have to do myObject.opt(key) to make sure it is there
First question: you should use a library to parse JSON, it's simpler that way. Try gson. You should create a class, which holds the parsed object, like:
public class Taxi implements Serializable {
private static final long serialVersionUID = 1L;
#SerializedName("idTaxi")
private Integer idTaxi;
#SerializedName("name")
private String name;
//getter, setters, constructor, etc
}
Then when you get the JSON object, you can parse it:
Gson gson = new Gson();
Reader reader = new InputStreamReader(SOURCE_STREAM);
Taxi[] response = gson.fromJson(reader, Taxi[].class);
Second question: i think a ListView would be good for you. You can read a full tutorial about it here