JSON Nested Objects - java

I'm working with a JSON file that has nested objects like this,
{
"LocId":99,
"typeId":99,
"name":"foo",
"parentId":99,
"geoCode":
{
"type":"bang",
"coordinates":
[{
"latitude":99.0,
"longitude":99.0
}]
}
}
I created a container to hold the JSON file in a class like this,
public class Location_JSON {
private LocId id;
// +getter+setter
#Override
public String toString() {
return id.toString();
}
public static class LocId {
private Long locId;
private Long typeId;
private String name;
private Long parentId;
private GeoCode geoCode;
// +getters+setters
#Override
public String toString() {
return "{\"locId\":" + locId
+ ", \"typeId\":" + typeId
+ ", \"name\":" + name
+ ", \"geoCode\":" + geoCode.toString() + "}";
}
}
public static class GeoCode {
private String type;
private Coordinates coordinates;
// +getter+setter
#Override
public String toString() {
//return "{\"type\":" + type + "}";
return "{\"type\":" + type
+ ", \"coordinates\":" + coordinates.toString() + "}";
}
}
public static class Coordinates {
private Double latitude;
private Double longitude;
// +getter+setter
#Override
public String toString() {
return "[{\"latitude\":" + latitude
+ ", \"longitude\":" + longitude + "}]";
}
}
}
To test that everything works I read in the JSON object as a string like this,
String str = "the JSON string shown above";
InputStream is = new ByteArrayInputStream(str.getBytes());
BufferedReader br = new BufferedReader(new InputStreamReader(is));
Location_JSON locations = new Gson().fromJson(br, Location_JSON.class);
System.out.println(locations.toString());
This produces a NullPointerException!
I implemented two of the Deserializer solutions found in this SO post,
Get nested JSON object with GSON using retrofit but it still created the same null error.
According to this SO post,
Java - Gson parsing nested within nested what I have should be close.
I tested my code without the nested objects i.e., I erased the nested objects from both the string and the Location_JSON container, and everything worked. So I believe this is a JSON nested object problem.
UPDATE:
If you're looking at this post I just want to point out that I accepted chengpohi's answer because it solved my initial question and chengpohi was the first to provide an answer. I did however have a second problem that I did not discover until after this question was solved. Sachin Gupta provided a working solution to my second problem. If you're using this post please check out BOTH answers down below. Thank you.

Location_JSON locations = new Gson().fromJson(br, Location_JSON.class);
it should be:
LocId locations = new Gson().fromJson(br, LocId.class);
You get NullPointerException, because your LocId have not be initiliazed. Your JSON is a object of LocId.
and your JSON:
"coordinates":
[{
"latitude":99.0,
"longitude":99.0
}]
should be:
"coordinates":
{
"latitude":99.0,
"longitude":99.0
}

As already stated in above answer, you have to use LocId class as primary one.
now for java.lang.IllegalStateException you can modify GeoCode class to use array of Coordinates class. like :
public static class GeoCode {
private String type;
private Coordinates []coordinates;
// +getter+setter
#Override
public String toString() {
return "GeoCode [type=" + type + ", coordinates=" + Arrays.toString(coordinates) + "]";
}
}

Related

Parsing an array of non-homogeneous JSON Objects with Jackson

I have a situation where I need to parse an array of JSON objects that are not identical.
So for example:
[
{ "type": "type1", ..... type1 contents .... },
{ "type": "type2", ..... type2 contents .... },
....
{ "type": "type1", ..... type1 contents .... }
]
The number of types is limited and the contents of each type are well can be defined but it is not possible to define a single type of object that will hold the contents.
Is there a way to parse them with Jackson?
P.S. I am trying to avoid writing a custom parser if I can help it.
I would use
com.fasterxml.jackson.databind.JsonNode.
JsonNode parsed = objectMapper
.readValue("[{\"name\": \"a\"},{\"type\":\"b\"}]", JsonNode.class);
This class has tons of utility methods to work with.
Or specific for arrays you can use:
com.fasterxml.jackson.databind.node.ArrayNode
ArrayNode value = objectMapper
.readValue("[{\"name\": \"a\"},{\"type\":\"b\"}]", ArrayNode.class);
EDIT
Sorry, I have misread your question, you can use #JsonTypeInfo for polymorphic serialization/deserialization:
public static void main(String args[]) throws JsonProcessingException {
//language=JSON
String data = "[{\"type\":\"type1\", \"type1Specific\":\"this is type1\"},{\"type\":\"type2\", \"type2Specific\":\"this is type2\"}]";
ObjectMapper objectMapper = new ObjectMapper();
List<BaseType> parsed = objectMapper.readValue(data, new TypeReference<List<BaseType>>() {});
System.out.println(parsed);
}
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", include = JsonTypeInfo.As.PROPERTY)
#JsonSubTypes(value = {
#JsonSubTypes.Type(value = Type1.class, name = "type1"),
#JsonSubTypes.Type(value = Type2.class, name = "type2")
})
static public abstract class BaseType {
public String type;
}
static public class Type1 extends BaseType {
public String type1Specific;
#Override
public String toString() {
return "Type1{" +
"type1Specific='" + type1Specific + '\'' +
'}';
}
}
static public class Type2 extends BaseType {
public String type2Specific;
#Override
public String toString() {
return "Type2{" +
"type2Specific='" + type2Specific + '\'' +
'}';
}
}
Here are the docs:
https://github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization
Hope this helps.
And the result would be:
[Type1{type1Specific='this is type1'}, Type2{type2Specific='this is type2'}]
We can use List.class to map this JSON Array with different types of objects that hold the content. It will return the List of LinkedHashMaps. Different content will be mapped to LinkedHashMap.
#Test
public void testLoadCustom() {
String json = "[{\"a\":\"A\" } , {\"b\":\"B\" , \"c\":\"C\" } , {\"d\":\"D\" } ]";
try {
List custom = objectMapper.readValue(json, List.class);
System.out.println(custom);
} catch (Exception ex) {
ex.getStackTrace();
}
}
// Output [{a=A}, {b=B, c=C}, {d=D}]

Jackson JSON key as value in Java

I'm using Jackson in Spring MVC application. I want to use a String value as key name for Java POJO --> JSON
"record": {
"<Dynamic record name String>": {
"value": {
....
}
}
}
So the dynamic record name String could be "abcd","xyz" or any other string value. How can I define my "record" POJO to have a key like that ?
Unfortunately, you cannot have dynamic fields in Java classes (unlike some other languages), so you have two choices:
Using Maps
Using JSON objects (i.e. JsonNode in case of Jackson)
Suppose, you have a data like this:
{
"record": {
"jon-skeet": {
"name": "Jon Skeet",
"rep": 982706
},
"darin-dimitrov": {
"name": "Darin Dimitrov",
"rep": 762173
},
"novice-user": {
"name": "Novice User",
"rep": 766
}
}
}
Create two classes to capture it, one for user and another for the object itself:
User.java:
public class User {
private String name;
private Long rep;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Long getRep() { return rep; }
public void setRep(Long rep) { this.rep = rep; }
#Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", rep=" + rep +
'}';
}
}
Data.java:
public class Data {
private Map<String, User> record;
public Map<String, User> getRecord() { return record; }
public void setRecord(Map<String, User> record) { this.record = record; }
#Override
public String toString() {
return "Data{" +
"record=" + record +
'}';
}
}
Now, parse the JSON (I assume there is a data.json file in the root of your classpath):
public class App {
public static void main(String[] args) throws Exception {
final ObjectMapper objectMapper = new ObjectMapper();
System.out.println(objectMapper.readValue(App.class.getResourceAsStream("/data.json"), Data.class));
System.out.println(objectMapper.readTree(App.class.getResourceAsStream("/data.json")));
}
}
This will output:
Data{record={jon-skeet=User{name='Jon Skeet', rep=982706}, darin-dimitrov=User{name='Darin Dimitrov', rep=762173}, novice-user=User{name='Novice User', rep=766}}}
{"record":{"jon-skeet":{"name":"Jon Skeet","rep":982706},"darin-dimitrov":{"name":"Darin Dimitrov","rep":762173},"novice-user":{"name":"Novice User","rep":766}}}
In case of a Map you can use some static classes, like User in this case, or go completely dynamic by using Maps of Maps (Map<String, Map<String, ...>>. However, if you find yourself using too much maps, consider switching to JsonNodes. Basically, they are the same as Map and "invented" specifically for highly dynamic data. Though, you'll have some hard time working with them later...
Take a look at a complete example, I've prepared for you here.
This is in Kotlin but I have found a solution to the same problem using Jackson.
You don't need the root node "record", so you will need to get rid of it or start one node deeper(you're on your own there) but to turn the list of records that are children of their id into a list of records with id in the object follows:
val node = ObjectMapper().reader().readTree(json)
val recordList = mutableListOf<Record>()
node.fields().iterator().forEach {
val record = record(
it.key,
it.value.get("name").asText(),
it.value.get("rep").asText()
)
recordList.add(event)
}
node.fields() returns a map of children(also maps)
iterating through the parent map you will get the id from the key and then the nested data is in the value (which is another map)
each child of fields is key : value where
key = record id
value = nested data (map)
This solution, you don't need multiple classes to deserialize a list of classes.
I have my data in this format:
{
"0" : {"a": {}}, {"b": {}}, ...
"1" : {"c": {}}, {"d": {}}, ...
.
.
.
}
I am able to capture it into a map using the dynamic capture feature of jackson by using #JsonAnySetter annotation.
public class Destination{
Map<String, Object> destination = new LinkedHashMap<>();
#JsonAnySetter
void setDestination(String key, Object value) {
destination.put(key, value);
}
}

Gson toJson(), weird behavior (produce empty json)

I have problems serializing / deserializing this class with Gson:
public class Test {
#SerializedName("id")
private String mId;
public String getId() { return mId; }
public static Test fromJson(String json) { return new Gson().fromJson(json, Test.class); }
public String toJson() { return new Gson().toJson(this, Test.class); }
}
If I run this:
Test test = Test.fromJson("{\"id\":\"1465988493\"}");
Log.i(TAG, "Test: " + test.toJson());
//Log.i(TAG, "Test id: " + test.getId());
It prints:
Test: {}
But if I run this:
Test test = Test.fromJson("{\"id\":\"1465988493\"}");
Log.i(TAG, "Test: " + test.toJson());
Log.i(TAG, "Test id: " + test.getId());
It works as expected and prints:
Test: {"id":"1465988493"}
Test id: 1465988493
So calling the getter AFTER calling toJson made toJson() to work. WTF???
Last thing, if I initialize the id to null:
public class Test {
#SerializedName("id")
private String mId = null; // <- Init to null
public String getId() { return mId; }
public static Test fromJson(String json) { return new Gson().fromJson(json, Test.class); }
public String toJson() { return new Gson().toJson(this, Test.class); }
}
Then everything works as expected, and this code:
String testJson = "{\"id\":\"1465988493\"}";
Test test = Test.fromJson(testJson);
Log.i(TAG, "Test: " + test.toJson());
//Log.i(TAG, "Test id: " + test.getId());
Prints:
Test: {"id":"1465988493"}
So, I have the solution (initialize all my fields to null), but I'd like to understand what's wrong??
There is just proguard problem. If you use proguard just keep in mind the proguard can remove some fields from class if you don't use it. For example your app doesn't use getters of class. So easy way just add annotation to keep it like:
#SerializedName("id")
#Keep
private String mId;
Or add keep rule to your proguard file.

Deserialize a complex Json Object using GSON in Java

Using this as a reference I have described the structure of my Json data and can grab the information as needed until I get to nest records and arrays.
Parsing a complex Json Object using GSON in Java
However my JSON data is nested several times over. For example;
{
"meetings": [
{
"meetingName": "GaryVon",
"location": "USA",
"meetingType": "P",
"meetingDate": "2016-03-25",
"weatherCondition": "FINE",
"showCode": {
"meetingCode": "A",
"scheduledType": "R"
},
"venueType": "ANI",
"showPools": [
{
"showProduct": "GaryVon",
"showStatus": "Open",
}
]
}
]
}
I have my wrapper and classes describing the format of the json data. Each class in a new java file.
public class meetingContainer {
public List<meetings> meetings;
}
Top level class
public class meetings {
private String meetingName;
private String location;
private String meetingType;
private String meetingDate;
private String weatherCondition;
private ShowCode showCode;
private String venueType;
private ShowPools[] showPools;
public String getMeetingName() { return meetingName; }
public String getLocation() { return location; }
public String getMeetingType() { return meetingType; }
public String getMeetingDate() { return meetingDate; }
public String getWeatherCondition() { return weatherCondition; }
public ShowCode getShowCode() { return showCode; }
public String getVenueType() { return venueType; }
public ShowPools[] getShowPools() { return showPools; }
}
2nd Level class
public class ShowCode {
private String meetingCode;
private String scheduledType;
public String getMeetingCode() { return meetingCode; }
public String getScheduledType() { return scheduledType; }
}
2nd Level Class
public class ShowPools {
private String showProduct;
private String showStatus;
public String getShowProduct() { return showProduct; }
public String getShowStatus() { return showStatus; }
}
I then try to parse it and grab the data which works fine until I get into nested arrays/records
Gson g = new Gson();
meetingContainer mc = g.fromJson(jsonMeetingsString, meetingContainer.class);
for(meetings m: mc.meetings){
System.out.println(m.getMeetingName()); //Result = "GaryVon"
System.out.println(m.getLocation()); //Result = "USA"
System.out.println(m.getmeetingType()); //Result = "P"
System.out.println(m.getShowCode()); //Result = "packagename.ShowCode#210366b4"
}
My question is how to I declare nested arrays/records and then call those methods from different classes i.e. Call the methods in showcode and showpools. The other post did not say how. Sorry if this is a simple answer as I'm new to java.
m.getShowCode()
This returns a reference of type ShowCode, to access inner values use the getters, for example :
m.getShowCode().getMeetingCode()
You should use a list for showPools
private List<ShowPools> showPools;
Your provided JSON string is invalid. It has one extra , -
{
"showProduct": "GaryVon",
"showStatus": "Open",
^
Answer for your question you asked in comment : m.getShowCode().getShowProduct() is invalid since showCode node has only two attributes meetingCode and scheduledType.
below code is listing all values of JSON. Let me know if it not covers your question
Gson g = new Gson();
meetingContainer mc = g.fromJson(jsonMeetingsString,
meetingContainer.class);
for (meetings m : mc.meetings) {
System.out.println("meetingName: " + m.getMeetingName());
System.out.println("location: "+ m.getLocation());
System.out.println("meetingType: "+ m.getMeetingType());
System.out.println("meetingDate: "+ m.getMeetingDate());
System.out.println("weatherConditio: "+ m.getWeatherCondition());
System.out.println("showCode->meetingCode: "+ m.getShowCode().getMeetingCode());
System.out.println("showCode->scheduledType: "+ m.getShowCode().getScheduledType());
System.out.println("venueType: "+ m.getVenueType());
for(ShowPools showPool : m.getShowPools()){
System.out.println("showPools->showProduct: "+ showPool.getShowProduct());
System.out.println("showPools->showStatus: "+ showPool.getShowStatus());
}
}
Output:
meetingName: GaryVon
location: USA
meetingType: P
meetingDate: 2016-03-25
weatherConditio: FINE
showCode->meetingCode: A
showCode->scheduledType: R
venueType: ANI
showPools->showProduct: GaryVon
showPools->showStatus: Open

Why do I get "Failed to bounce to type" when I turn JSON from Firebase into Java objects?

[Disclosure: I am an engineer at Firebase. This question is meant to be a reference question to answer many questions in one go.]
I have the following JSON structure in my Firebase database:
{
"users": {
"-Jx5vuRqItEF-7kAgVWy": {
"handle": "puf",
"name": "Frank van Puffelen",
"soId": 209103
},
"-Jx5w3IOHD2kRFFgkMbh": {
"handle": "kato",
"name": "Kato Wulf",
"soId": 394010
},
"-Jx5x1VWs08Zc5S-0U4p": {
"handle": "mimming",
"name": "Jenny Tong",
"soId": 839465
}
}
}
I am reading this with the following code:
private static class User {
String handle;
String name;
public String getHandle() { return handle; }
public String getName() { return name; }
}
Firebase ref = new Firebase("https://stackoverflow.firebaseio.com/32108969/users");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot usersSnapshot) {
for (DataSnapshot userSnapshot : usersSnapshot.getChildren()) {
User user = userSnapshot.getValue(User.class);
System.out.println(user.toString());
}
}
#Override
public void onCancelled(FirebaseError firebaseError) { }
});
But I get this error:
Exception in thread "FirebaseEventTarget" com.firebase.client.FirebaseException: Failed to bounce to type
How can I read my users into Java objects?
Firebase uses Jackson to allow serialization of Java objects to JSON and deserialization of JSON back into Java objects. You can find more about Jackson on the Jackson website and this page about Jackson annotations.
In the rest of this answer, we’ll show a few common ways of using Jackson with Firebase.
Loading complete users
The simplest way of loading the users from Firebase into Android is if we create a Java class that completely mimics the properties in the JSON:
private static class User {
String handle;
String name;
long stackId;
public String getHandle() { return handle; }
public String getName() { return name; }
public long getStackId() { return stackId; }
#Override
public String toString() { return "User{handle='"+handle+“', name='"+name+"', stackId="+stackId+"\’}”; }
}
We can use this class in a listener:
Firebase ref = new Firebase("https://stackoverflow.firebaseio.com/32108969/users");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot usersSnapshot) {
for (DataSnapshot userSnapshot : usersSnapshot.getChildren()) {
User user = userSnapshot.getValue(User.class);
System.out.println(user.toString());
}
}
#Override
public void onCancelled(FirebaseError firebaseError) { }
});
You may note that the User class follow the JavaBean property pattern. Every JSON property maps by a field in the User class and we have a public getter method for each field. By ensuring that all properties are mapped with the exact same name, we ensure that Jackson can automatically map them.
You can also manually control the mapping by putting Jackson annotations on your Java class, and its fields and methods. We’ll cover the two most common annotations (#JsonIgnore and #JsonIgnoreProperties) below.
Partially loading users
Say that you only care about the user’s name and handle in your Java code. Let’s remove the stackId and see what happens:
private static class User {
String handle;
String name;
public String getHandle() { return handle; }
public String getName() { return name; }
#Override
public String toString() {
return "User{handle='" + handle + “\', name='" + name + "\’}”;
}
}
If we now attach the same listener as before and run the program, it will throw an exception:
Exception in thread "FirebaseEventTarget" com.firebase.client.FirebaseException: Failed to bounce to type
at com.firebase.client.DataSnapshot.getValue(DataSnapshot.java:187)
at com.firebase.LoadPartialUsers$1.onDataChange(LoadPartialUsers.java:16)
The “failed to debounce type” indicates that Jackson was unable to deserialize the JSON into a User object. In the nested exception it tells us why:
Caused by: com.shaded.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "stackId" (class com.firebase.LoadPartialUsers$User), not marked as ignorable (2 known properties: , "handle", "name"])
at [Source: java.io.StringReader#43079089; line: 1, column: 15] (through reference chain: com.firebase.User["stackId"])
at com.shaded.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:79)
Jackson found a property stackId in the JSON and doesn’t know what to do with it, so it throws an exception. Luckily there is an annotation that we can use to tell it to ignore specific properties from the JSON when mapping it to our User class:
#JsonIgnoreProperties({ "stackId" })
private static class User {
...
}
If we not run the code with our listener again, Jackson will know that it can ignore stackId in the JSON and it will be able to deserialize the JSON into a User object again.
Since adding properties to the JSON is such a common practice in Firebase applications, you may find it more convenient to simply tell Jackson to ignore all properties that don’t have a mapping in the Java class:
#JsonIgnoreProperties(ignoreUnknown=true)
private static class User {
...
}
Now if we add properties to the JSON later, the Java code will still be able to load the Users. Just keep in mind that the User objects won’t contain all information that was present in the JSON, so be careful when writing them back to Firebase again.
Partially saving users
One reason why it is nice to have a custom Java class, is that we can add convenience methods to it. Say that we add a convenience method that gets the name to display for a user:
private static class User {
String handle;
String name;
public String getHandle() { return handle; }
public String getName() { return name; }
#JsonIgnore
public String getDisplayName() {
return getName() + " (" + getHandle() + ")";
}
#Override
public String toString() {
return "User{handle='" + handle + "\', name='" + name + "\', displayName='" + getDisplayName() + "'}";
}
}
Now let's read the users from Firebase and write them back into a new location:
Firebase srcRef = new Firebase("https://stackoverflow.firebaseio.com/32108969/users");
final Firebase copyRef = new Firebase("https://stackoverflow.firebaseio.com/32108969/copiedusers");
srcRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot usersSnapshot) {
for (DataSnapshot userSnapshot : usersSnapshot.getChildren()) {
User user = userSnapshot.getValue(User.class);
copyRef.child(userSnapshot.getKey()).setValue(user);
}
}
#Override
public void onCancelled(FirebaseError firebaseError) { }
});
The JSON in the copiedusers node looks like this:
"copiedusers": {
"-Jx5vuRqItEF-7kAgVWy": {
"displayName": "Frank van Puffelen (puf)",
"handle": "puf",
"name": "Frank van Puffelen"
},
"-Jx5w3IOHD2kRFFgkMbh": {
"displayName": "Kato Wulf (kato)",
"handle": "kato",
"name": "Kato Wulf"
},
"-Jx5x1VWs08Zc5S-0U4p": {
"displayName": "Jenny Tong (mimming)",
"handle": "mimming",
"name": "Jenny Tong"
}
}
That’s not the same as the source JSON, because Jackson recognizes the new getDisplayName() method as a JavaBean getter and thus added a displayName property to the JSON it outputs. We solve this problem by adding a JsonIgnore annotation to getDisplayName().
#JsonIgnore
public String getDisplayName() {
return getName() + "(" + getHandle() + ")";
}
When serializing a User object, Jackson will now ignore the getDisplayName() method and the JSON we write out will be the same as what we got it.
The 9.x (and higher) versions of the Firebase SDK for Android/Java stopped including Jackson for serializing/deserializing Java<->JSON. The newer SDK instead provides a minimal set of custom annotations to allow control over the most common customization needs, while having a minimal impact on the resulting JAR/APK size.
My original answer is still valid if you're:
Using the Firebase 2.x SDKs
Using the Firebase 9.0 or higher SDKs, but use Jackson for serializing/deserializing Java<->JSON.
The rest of this answer covers how to handle serialization/deserialization scenarios in Firebase SDK 9.0 or higher.
Data structure
We'll start with this JSON structure in our Firebase Database:
{
"-Jx86I5e8JBMZ9tH6W3Q" : {
"handle" : "puf",
"name" : "Frank van Puffelen",
"stackId" : 209103,
"stackOverflowId" : 209103
},
"-Jx86Ke_fk44EMl8hRnP" : {
"handle" : "mimming",
"name" : "Jenny Tong",
"stackId" : 839465
},
"-Jx86N4qeUNzThqlSMer" : {
"handle" : "kato",
"name" : "Kato Wulf",
"stackId" : 394010
}
}
Loading complete users
At its most basic, we can load each user from this JSON into the following Java class:
private static class CompleteUser {
String handle;
String name;
long stackId;
public String getHandle() { return handle; }
public String getName() { return name; }
public long getStackId() { return stackId; }
#Override
public String toString() { return "User{handle='"+handle+"', name='"+name+"', stackId="+stackId+ "'}"; }
}
If we declare the fields to be public, we don't even need the getters:
private static class CompleteUser {
public String handle;
public String name;
public long stackId;
}
Partially loading users
We can also partially load a user, for example with:
private static class PartialUser {
String handle;
String name;
public String getHandle() {
return handle;
}
public String getName() { return name; }
#Override
public String toString() {
return "User{handle='" + handle + "', NAME='" + name + "''}";
}
}
When we use this class to load the users from the same JSON, the code runs (unlike the Jackson variant mentioned in my other answer). But you'll see a warning in your logging output:
WARNING: No setter/field for stackId found on class Annotations$PartialUser
So get rid of that, we can annotate the class with #IgnoreExtraProperties:
#IgnoreExtraProperties
private static class PartialUser {
String handle;
String name;
public String getHandle() {
return handle;
}
public String getName() { return name; }
#Override
public String toString() {
return "User{handle='" + handle + "', NAME='" + name + "''}";
}
}
Partially saving users
As before, you might want to add a calculated property to the user. You'd want to ignore such a property when saving the data back to the database. To do this, you can annotate the property/getter/setter/field with #Exclude:
private static class OvercompleteUser {
String handle;
String name;
long stackId;
public String getHandle() { return handle; }
public String getName() { return name; }
public long getStackId() { return stackId; }
#Exclude
public String getTag() { return getName() + " ("+getHandle()+")"; }
#Override
public String toString() { return "User{handle='"+handle+"', name='"+name+"', stackId="+stackId+ "'}"; }
}
Now when writing a user to the database, the value of getTag() will be ignored.
Using a different property name in the JSON than in the Java code
You can also specify what name a field/getter/setter from the Java code should get in the JSON in the database. To do this: annotate the field/getter/setter with #PropertyName().
private static class UserWithRenamedProperty {
String handle;
String name;
#PropertyName("stackId")
long stackOverflowId;
public String getHandle() { return handle; }
public String getName() { return name; }
#PropertyName("stackId")
public long getStackOverflowId() { return stackOverflowId; }
#Override
public String toString() { return "User{handle='"+handle+"', name='"+name+"', stackId="+stackOverflowId+ "'}"; }
}
In general it's best to use the default mapping between Java<->JSON that the Firebase SDK uses. But #PropertyName may be needed when you have a pre-existing JSON structure that you can't otherwise map to Java classes.
Because your wrong query path folder in root.this is example
My code:
private void GetUpdates(DataSnapshot snapshot){
romchat.clear();
for (DataSnapshot ds: snapshot.getChildren()){
Rowitemroom row = new Rowitemroom();
row.setCaption(ds.getValue(Rowitemroom.class).getCaption());
row.setFileUrl(ds.getValue(Rowitemroom.class).getFileUrl());
romchat.add(row);
/* Rowitemroom row = snapshot.getValue(Rowitemroom.class);
String caption = row.getCaption();
String url = row.getFileUrl();*/
}
if (romchat.size()>0){
adapter = new CustomRoom(context,romchat);
recyclerView.setAdapter(adapter);
}else {
Toast.makeText(context, "No data", Toast.LENGTH_SHORT).show();
}
}
db_url ="your apps`enter code here`.appspot.com/admins"

Categories