We have ran into an issue with serialisation over JSON when using Firestore as our database.
When writing dates to Firestore it’s recommended that we use the TimeStamp object. We’re happy with that. I have a converter that converts all my DateTime’s to TimeStamps when doing the toJson and fromJson. So reading and writing to Firestore from my dart client works fine.
The problem comes in when we use an api endpoint and send the data over http using json encoding. We’ve realised that we cannot send a TimeStamp object over json. We want to avoid as much as possible the usage of multiple models to represent the same data. So I’m trying to figure out how can we write raw time stamps to firestore.
Now leading to my question.
If I wanted to write a TimeStamp to firestore, without using the TimeStamp type how would I do that? It must be stored in some way, at the moment I can’t find that through firestore UI or local emulator UI.
I’d rather serialise to and from TimeStampRaw than rely on the TimeStamp object because of the lack of fromJson / toJson in it.
Edit: For Clarity
toJson() => Writing to Firestore directly from app we use a firestore.TimeStamp type and Firestore understands it great
fromJson() => Reading from firestore directly works great
toJson() => Post to our backend. There’s no TimeStamp type encoding so we can’t send it as a timestamp. This is the problem 1
fromJson() => Reading a response from the backend. Can’t serialise a timestamp from a string. This is problem 2
We want to use the same toJson and fromJson functions. We can’t use millisecondsSinceEpoch as a String because then we lose accurate orderBy? As mentioned here . Hence me asking for the way to store TimeStamp as a raw value that Firestore will interpret as a TimeStamp
There doesn’t seem to be a raw TimeStamp format that would make Firestore automatically update the type of the date to a timestamp. So what we decided for now is to write a custom converter for the fromJson and write a second toJsonApi call that converts a TimeStamp into a known format for the Api. This way I can call my normal toJson for writing directly to Firestore and the custom toJson function when posting to the Api. It’s an extra method per object, but at least we can use the same models across firestore and our api.
I created a custom fromJson function that will check for all keys ending in
_at which is our convention for any property that reflects time. I will then check the value of that property and:
- If it’s a String I’ll assume it’s a DateTime.iso8601() and parse it to a DateTime
- If it’s a TimeStamp I’ll call .toDate on it.
I do the normal toJson call that’s generated. I then inspect that map for keys ending in
_at and if the type is TimeStamp I will call toDate.toIso8601 on it and send that to the api.
This is not ideal but I’d rather have it work and then improve on it later if there’s a better way.
Answered By – Filled Stacks
Answer Checked By – Senaida (FlutterFixes Volunteer)