10

I am getting following exception while updating an existing value in the Firebase using updateChildren method.

com.firebase.client.FirebaseException: Failed to parse node with class class com.shajeelafzal.quicktasks_app.models.HashTagModel
  at com.firebase.client.snapshot.NodeUtilities.NodeFromJSON(NodeUtilities.java:84)
  at com.firebase.client.snapshot.NodeUtilities.NodeFromJSON(NodeUtilities.java:12)
  at com.firebase.client.utilities.Validation.parseAndValidateUpdate(Validation.java:127)
  at com.firebase.client.Firebase.updateChildren(Firebase.java:438)
  at com.shajeelafzal.quicktasks_app.fragments.AddEditTaskFragment$4.onDataChange(AddEditTaskFragment.java:408)

My model looks like this:

public class HashTagModel implements Parcelable {

    private HashMap<String, Object> timeStampLastUsed;
    @Expose
    private String name;
    @Expose
    private String createByUserEmail;
    private List<String> tasksKeys;

    public HashTagModel() {
    }

    public HashTagModel(HashMap<String, Object> timeStampLastUsed, String name,
                        String createByUserEmail, ArrayList<String> tasksKeys) {
        this.timeStampLastUsed = timeStampLastUsed;
        this.name = name;
        this.createByUserEmail = createByUserEmail;
        this.tasksKeys = tasksKeys;
    }
}

JSON Object that I want to update looks like this on Firebase:

"hashTags" : {
    "USER_EMAIL" : {
      "USA" : {
        "createByUserEmail" : "USER_EMAIL",
        "name" : "#USA",
        "tasksKeys" : [ "-K6mS36uhKthKf1-1pF1" ],
        "timeStampLastUsed" : {
          "timestamp" : 1451514461234
        }
      }
    }
  }

And my onDateChange method looks like this:

public void onDataChange(DataSnapshot dataSnapshot) {
    /** if the hash tag does not exists already then create new one. */
    if (dataSnapshot.getValue() == null) {
        HashMap<String, Object> timestampJoined = new HashMap<>();
        timestampJoined.put(Constants.FIREBASE_PROPERTY_TIMESTAMP, ServerValue.TIMESTAMP);

        ArrayList<String> keysList = new ArrayList<String>();
        keysList.add(key);

        HashTagModel hashTag = new HashTagModel(timestampJoined, "#" + mHashTags.get(finalI),
                Utils.decodeEmail(mEncodedEmail), keysList);
        finalHashTagLocation.setValue(hashTag);
    } else {

        HashTagModel hashtaghModel = dataSnapshot.getValue(HashTagModel.class);

        hashtaghModel.getTasksKeys().add(key);

        /* HashMap for data to update */
        HashMap<String, Object> updateUserTaskData = new HashMap<>();


        Utils.updateMapForAllWithValue(null, mHashTags.get(finalI), mEncodedEmail,
                updateUserTaskData, "", hashtaghModel, Constants.FIREBASE_LOCATION_USER_HASH_TAGS);


        /** update the Hash Tag */
        finalHashTagLocation.updateChildren(updateUserTaskData, new Firebase.CompletionListener() {
            @Override
            public void onComplete(FirebaseError firebaseError, Firebase firebase) {
                Log.i("", "");
            }
        });
    }

    getActivity().finish();
}
5
  • Please include the actual JSON text from you Firebase database. You can get it by clicking the Export button in the Firebase dashboard and it will allow us to copy/paste the JSON for testing (or into an answer). Commented Dec 30, 2015 at 22:54
  • @FrankvanPuffelen i added the JSON text. Commented Dec 30, 2015 at 22:59
  • Thanks. We're also missing the code that writes to Firebase (in onDataChange()). And is the HashTagModel class really needed (and does it need to be this big) to reproduce the problem? Commented Dec 30, 2015 at 23:01
  • @FrankvanPuffelen i can remove the Parcelable code. I thought i might help to understand. I am adding the code that is supposed to update. Commented Dec 30, 2015 at 23:03
  • I'm pretty sure you're being affected by the same problem as described here: stackoverflow.com/questions/32848024/…. You cannot pass Java classes into updateChildren(). My answer on that question has a workaround for this. Commented Dec 31, 2015 at 5:44

1 Answer 1

15

Unlike the setValue() method, updateChildren() does not perform a Java-to-JSON conversion on the value(s) you pass in.

You're passing a HashMap<String, Object> into updateChildren(), which fits the contract of that API. But I'm pretty sure in some of the values you have a Java object (likely a HashTagModel) that is not directly mapped to a JSON type.

But what you can do is convert the POJO into a Map with:

Map<String, Object> hashtaghMap = new ObjectMapper().convertValue(hashtaghModel, Map.class);

Then you can put the map of values into the values that you're passing into updateChildren().

Sign up to request clarification or add additional context in comments.

4 Comments

@FrankvanPuffelen what about now that jackson is no more used by FirebaseDatabase? Should we import it as a dependency to achieve the same result? I'd rather not, since from what I read one of the reason of its removal was a concern for the final apk size. (Ref. stackoverflow.com/questions/37335712/…)
If you find a need that our new serialization/deserialization doesn't handle, you can use Jackson. See this answer for how to do that. And don't forget to also let us know about your use-case, so that we can consider adding support for it.
@FrankvanPuffelen thanks for the quick reply. My use case is the very same of this answer: to use updateChildren without the need to convert the pojo to a map manually. You suggested to use ObjectMapper but it is a Jackson class, so I was wondering if we can achieve the same result with the FirebaseDatabase API. Am I missing something? (And please forgive my ignorance, why updateChidren doesn't allow pojos as setValue does? If it is feasable to have a corresponding method that allows pojos, I would ask support for it instead :) )
@FrankvanPuffelen I'm also backing up @Ena's question from above. Is there any way to use updateChildren without manually converting objects to maps?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.