I created an object to send some data to firebase. As an example, I use firebase user example:
public class User {
public String username;
public String email;
public User() {
// Default constructor required for calls to DataSnapshot.getValue(User.class)
}
public User(String username, String email) {
this.username = username;
this.email = email;
}
}
I want to encode property names that are sent to firebase. Currently keys are sent using variable names. I want to encode keys something like Useraname and Email, like Gson is doing. I don't want to change variable names.
#SerializateName("Username")
public String username;
#SerializateName("Username")
public String email;
I used #SerializateName(), but is not working. Same with #PropertyName that is used by Firebse, is not working. What I can use in order to serializare custom keys?
Update 1
public class Pojo {
#PropertyName("Guid")
public String guid;
#PropertyName("Name")
public String name;
public String getPojoGuid() {
return guid;
}
public void setPojoGuid(String guid) {
this.guid = guid;
}
}
As you can see in the image, it saves keys based on variable names. I changed property name from annotation for one field and when i save it, it ignores it, but when i change variable name, it save as new entry with key for that new varialbe name.
In this documentation is a method toMap(). If i do like that, is working (is not convenient for me), but is not working with #PropertyName.
Update 2
If i mark getters and setters with #Exclude and class with #IgnoreExtraProperties is working. I don't have to use toMap() method example from documetation. Is using specified name from #PropertyName. Not a good thing in my opinion, create confuses.
The Firebase SDK uses the annotation it finds for the property whenever it gets or sets its value. That means you need to consider how Firebase gets/sets the value, and annotate each place it looks.
Since you're declaring a getter method, Firebase will use that to get the value of the property. It will use the field for setting the value. So the annotation needs to be on both:
public class Pojo {
#PropertyName("Guid")
public String guid;
#PropertyName("Name")
public String name;
#PropertyName("Guid")
public String getPojoGuid() {
return guid;
}
#PropertyName("Guid")
public void setPojoGuid(String guid) {
this.guid = guid;
}
}
If you'd have getters and setters, the annotation would need to be on those, but not on the fields anymore:
public class Pojo {
private String guid;
private String name;
#PropertyName("Guid")
public String getPojoGuid() {
return guid;
}
#PropertyName("Guid")
public void setPojoGuid(String value) {
guid = value;
}
#PropertyName("Name")
public void setPojoGuid(String guid) {
this.guid = guid;
}
#PropertyName("Name")
public void setPojoGuid(String value) {
name = value;
}
}
What you are looking for is the feature of SDK Version 9.2 in which you can now use a new #PropertyName attribute to specify the name to use when serializing a field from a Java model class to the database. This replaces the #JsonProperty attribute.
#PropertyName("Username")
public String username;
#PropertyName("Email")
public String email;
See also this post in which Frank van Puffelen explains very clearly this concept.
#PropertyName :
Marks a field to be renamed when serialized. link
you have to use #PropertyName with public fields and no need for getters/setters
Related
I have a pretty simple Enum that I am using throughout my application for Gender and I need to have a settings page where the user can change it, but I can't find any way to use an Enum in a ListPreference. I am using a PreferenceFragment to build the Preferences Screen, but I can't find a way to use the Enum I have as the entries and entryValues for the ListPreference.
The enum is very simple, just...
public enum Gender implements EnumSpinner {
MALE("Male", 0),
FEMALE("Female", 1),
NONE("Prefer not to say", -1);
private static SparceArray<Gender> genderMap = new SparceArray<>();
static {
for(Gender gender : Gender.values()) {
genderMap.put(gender.getValue(), gender);
}
}
private String name;
private int value;
Gender(String name, int value) {
this.name = name;
this.value = value;
}
public static Gender getGender(int val) { return genderMap.get(val); }
#Override
public String toString() { return name; }
public String getName() { return name; }
public int getValue() { return value; }
}
Is it possible to use in a ListPreference or am I going to have to create 2 string arrays in the strings.xml file and just use it that way?
SideNote, EnumSpinner is just an interface that allows me to use the enum in a spinner.
Please check in the google developers youtube channel, Android Performance Matters there is a video explaining why you would prefer not using enums in Android, there are other ways to get the same functionality.
Android has a Framework for Settings/Preferences, you can find an excellent tutorial here.
Buuilding Settings Screen Android
I push data to Firebase using Order object, the question is I want the first letter of every child name capital. I defined the property like "Complain" but in Firebase it still shows as "complain", I dont know how to make it.
The current structure of the Firebase:
The structure I want:
I defined the property like this:
#Data
public class Order implements Serializable {
#SerializedName("Complain")
private String Complain;
public Order() {
Complain = "";
}
public String getComplain() {
return Complain;
}
public void setComplain(String complain) {
Complain = complain;
}
}
I push data to Firebase like this:
Map<String, Object> map = new HashMap<>();
map.put(orderSavePath, order);
reference.updateChildren(map).addOnCompleteListener(listener);
The Firebase JSON serialization name is controlled by the annotation PropertyName.
public class Order implements Serializable {
private String Complain;
public Order() {
Complain = "";
}
#PropertyName("Complain")
public String getComplain() {
return Complain;
}
#PropertyName("Complain")
public void setComplain(String complain) {
Complain = complain;
}
}
The annotation needs to be on both the getter and the setter. Alternatively you can just use public fields and reduce the class to:
public class Order {
#PropertyName("Complain")
public String Complain;
}
I have a model class to store Firebase User information. Inside of the model class I have a HashMap to store all of the data inside. Once I have stored the data, the I push the Hashmap into the Firebase database. The values store fine, but I cannot access the values. Every time I try to access them, I get an error saying that I am attempting to invoke a virtual method on a null object reference.
mDatabase.child("users").child(mUserId).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot ChildSnapshot, String s) {
// These two lines of code give the error.
User author = ChildSnapshot.child("profile").getValue(User.class);
String author_username = author.getUsername();
These give me the error. I am attempting to grab data from the child of the snapshot. Why is this giving me an error? Is there a better way to do this?
JSON Firebase snapshot:
Model class:
//TODO model class for the user. This way I can set the values for each user. I will be adding more values in the future.
public class User {
public HashMap<String, String> hashMap = new HashMap<String,String>();
public User() {
}
public User(String username) {
hashMap.put("username",username);
}
public String getUsername(){
return hashMap.get("username");
}
}
In case somebody else was struggling with this issue, I wanted to give an answer. Inside of my ChildEventListener, the profile is the key in this situation so when I use ChildSnapshot.child("profile").getValue(User.class) it returns a null value. Also, (I'm not quite sure why this is) the value of the username was stored in a different class called User_message which was used to store the message. so my updated code looks something like this:
mDatabase.child("users").child(mUserId).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot ChildSnapshot, String s) {
User_message author = ChildSnapshot.getValue(User_message.class);
String author_username = author.getUsername();
I was facing the same problem and spent more than 5 hours. I added Default Constructor of the model and this solves my problem.
public class User {
public String email;
public String name;
public User() {
}
public User(String email, String name) {
this.email = email;
this.name = name;
}}
I hope this will help you. Thanks
I have a JSON string that contains a nested json like
{
"name": "name",
...
...
"profile": {
"id": 987,
"first_name": "first name"
...
...
}
}
I'm trying to map this JSON into Realm by using the method realm.createObjectFromJson(Class clazz, String string) and the problem is that the nested JSON is not mapped, the resulting RealmObject instance that corresponds to the "profile" has 0's and null's for all the fields. I used realm.beginTransaction() before the create operation, and realm.commitTransaction() after.
I'm using 'io.realm:realm-android:0.80.1' for my Android project.
Can you please tell me what am I doing wrong?
Thanks.
EDIT
These are my model classes. Simple RealmObjects linked together
public class SomeClass extends RealmObject {
private String name;
private Profile profile;
public Profile getProfile() {
return profile;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name= name;
}
}
public class Profile extends RealmObject {
private String firstName;
private String lastName;
private String birthdate;
private boolean newsLetter;
private boolean push;
private int userId;
private Date lastUpdate;
private RealmList<RealmAddress> addresses;
private RealmList<RealmGender> genders;
}
the profile class contains only getters and setters, and it contains other Strings and ints, which I deleted for the sake of simplicity.
Your JSON names doesn't match your child object field names which is why you don't see any data. Your profile name matches the field in SomeClass, which means the object gets created (with default values), but as none of the fields match in Profile, none of them are set.
firstName != first_name
userId != id
If you want to have separate names in your JSON and the Java models you should use something like GSON (http://realm.io/docs/java/#gson) as that is not yet supported by Realm directly.
use this :
public class Profile extends RealmObject {
private String first_name;
private int id;
...
}
check that you have the same names in JSON and your class model
I am using eclipse to create a app engine based application where I am also using app engine datastore(using JPA) using endpoints.
I wrote a test application with help from
https://developers.google.com/eclipse/docs/endpoints-addentities
and it went fine.
Now I want to create an entity where I define my own Key rather than it being automatically assigned by the system. Can someone help me as to what do I need to do that in my Notes.java entity class. By default the Notes.java like this.
package com.bfp.mypackage;
import javax.persistence.Entity;
import javax.persistence.Id;
#Entity
public class Note {
#Id
private String id;
private String emailAddress;
private String description;
public Note() {
}
public String getId() {
return id;
}
public String getDescription() {
return description;
}
public String getEmailAddress() {
return emailAddress;
}
public void setId(String idIn) {
this.id = idIn;
}
public void setDescription(String description) {
this.description = description;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
}
When I test this code I see the Note entity created in my dev app server admin console with the values(an emailAddress, a dsescription and an ID(I pass timestamp there)) I had supplied. I see two other fields created when I view the entity in admin console. One "Key" and other "Write ops". Now the "Key" field as I understand is the one generated automatically by java. Is there anyway I can set my emailAddress field as the Key? If so then what changes I need to do in above code. That way I can use emailAddress as the unique key for each entity.
You must set your email address as the "Key" name : a key is defined by either an auto-incremented long ID, or a user assigned key name that is unique for an entity kind.
I'm not the most experimented using JPA since I've used mostly JDO and the low level approach, but you might have to use directly the com.google.appengine.api.datastore.Key object instead of a java.lang.String attribute...
The low level API method is :
KeyFactory.createKey("EntityName", "whatever#domain.com");