{"id":20532401,"url":"https://github.com/unitvectory-labs/firestoreproto2json","last_synced_at":"2025-07-17T18:09:15.210Z","repository":{"id":224455663,"uuid":"763214485","full_name":"UnitVectorY-Labs/firestoreproto2json","owner":"UnitVectorY-Labs","description":"Helper library to convert Firestore Protocol Buffer to JSON Object","archived":false,"fork":false,"pushed_at":"2024-04-09T00:27:56.000Z","size":155,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-04-09T01:55:37.698Z","etag":null,"topics":["gcp-firestore","java-17","json"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/UnitVectorY-Labs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2024-02-25T20:56:03.000Z","updated_at":"2024-04-15T12:08:52.859Z","dependencies_parsed_at":"2024-02-26T04:24:42.610Z","dependency_job_id":"99f928da-437e-4c5d-889a-6dccc81933d4","html_url":"https://github.com/UnitVectorY-Labs/firestoreproto2json","commit_stats":null,"previous_names":["unitvectory-labs/firestoreproto2json"],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UnitVectorY-Labs%2Ffirestoreproto2json","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UnitVectorY-Labs%2Ffirestoreproto2json/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UnitVectorY-Labs%2Ffirestoreproto2json/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UnitVectorY-Labs%2Ffirestoreproto2json/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/UnitVectorY-Labs","download_url":"https://codeload.github.com/UnitVectorY-Labs/firestoreproto2json/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242138802,"owners_count":20078007,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gcp-firestore","java-17","json"],"created_at":"2024-11-16T00:14:48.190Z","updated_at":"2025-07-17T18:09:15.191Z","avatar_url":"https://github.com/UnitVectorY-Labs.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![GitHub release](https://img.shields.io/github/release/UnitVectorY-Labs/firestoreproto2json.svg)](https://github.com/UnitVectorY-Labs/firestoreproto2json/releases/latest) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![Active](https://img.shields.io/badge/Status-Active-green)](https://guide.unitvectorylabs.com/bestpractices/status/#active) [![Maven Central](https://img.shields.io/maven-central/v/com.unitvectory/firestoreproto2json)](https://central.sonatype.com/artifact/com.unitvectory/firestoreproto2json) [![javadoc](https://javadoc.io/badge2/com.unitvectory/firestoreproto2json/javadoc.svg)](https://javadoc.io/doc/com.unitvectory/firestoreproto2json) [![codecov](https://codecov.io/gh/UnitVectorY-Labs/firestoreproto2json/graph/badge.svg?token=N6CU9DZRIQ)](https://codecov.io/gh/UnitVectorY-Labs/firestoreproto2json)\n\n# firestoreproto2json\n\nJava helper library to convert Firestore Protocol Buffer to JSON Object\n\n## Purpose\n\nThis library takes the Protocol Buffer sent from Firestore for a document and converts it to a JSON Object. Firestore stores the underlying documents as Protocol Buffers and therefore that is what is sent to a Cloud Function when subscribed. While this is useful, when you have an event attached to Firestore to receive such as a Cloud Function that processes a change to the document.\n\nThis library takes the Protocol Buffer and converts it to a JSON Object using a set of assumptions that may or may not match how normal interactions with the document using the API. However, this conversion to JSON is likely useful for a generic implementation that needs to take an arbitrary document and convert it to the corresponding JSON representation.\n\n## Getting Started\n\nThis library requires Java 17 and is available in the Maven Central Repository:\n\n```\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.unitvectory\u003c/groupId\u003e\n    \u003cartifactId\u003efirestoreproto2json\u003c/artifactId\u003e\n    \u003cversion\u003e0.0.7\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n## Cloud Function Usage\n\nThe following example is adapted from the Java 17 example for a Cloud Function connected to Firestore. This library includes `com.google.cloud:google-cloudevent-types` and `com.google.protobuf:protobuf-java` as dependencies and therefore they do not need to be included again.\n\n```xml\n\u003cproject xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\"\u003e\n\u003cmodelVersion\u003e4.0.0\u003c/modelVersion\u003e\n\n\u003cgroupId\u003ecom.example.cloud.functions\u003c/groupId\u003e\n\u003cartifactId\u003efunctions-firebase-firestore\u003c/artifactId\u003e\n\n\u003cparent\u003e\n  \u003cgroupId\u003ecom.google.cloud.samples\u003c/groupId\u003e\n  \u003cartifactId\u003eshared-configuration\u003c/artifactId\u003e\n  \u003cversion\u003e1.2.0\u003c/version\u003e\n\u003c/parent\u003e\n\n\u003cproperties\u003e\n  \u003cmaven.compiler.release\u003e17\u003c/maven.compiler.release\u003e\n  \u003cproject.build.sourceEncoding\u003eUTF-8\u003c/project.build.sourceEncoding\u003e\n\u003c/properties\u003e\n\n\u003cdependencies\u003e\n  \u003cdependency\u003e\n    \u003cgroupId\u003ecom.unitvectory\u003c/groupId\u003e\n    \u003cartifactId\u003efirestoreproto2json\u003c/artifactId\u003e\n    \u003cversion\u003e0.0.6\u003c/version\u003e\n  \u003c/dependency\u003e\n  \u003cdependency\u003e\n    \u003cgroupId\u003ecom.google.cloud.functions\u003c/groupId\u003e\n    \u003cartifactId\u003efunctions-framework-api\u003c/artifactId\u003e\n    \u003cversion\u003e1.0.4\u003c/version\u003e\n    \u003cscope\u003eprovided\u003c/scope\u003e\n  \u003c/dependency\u003e\n\u003c/dependencies\u003e\n\n\u003c/project\u003e\n```\n\nThe following example taken from CloudFunction is adapted to show how firestoreproto2json can be used to convert the value and old value into a JSON string. If the value is not set a null value will be returned.\n\n```java\npackage functions;\n\nimport com.google.cloud.functions.CloudEventsFunction;\nimport com.google.events.cloud.firestore.v1.DocumentEventData;\nimport com.google.protobuf.InvalidProtocolBufferException;\nimport com.unitvectory.firestoreproto2json.FirestoreProto2Json;\nimport io.cloudevents.CloudEvent;\nimport java.util.logging.Logger;\n\npublic class FirebaseFirestore implements CloudEventsFunction {\n  private static final Logger logger = Logger.getLogger(FirebaseFirestore.class.getName());\n\n  @Override\n  public void accept(CloudEvent event) throws InvalidProtocolBufferException {\n    DocumentEventData firestoreEventData = DocumentEventData.parseFrom(event.getData().toBytes());\n\n    // Convert the value to JSON\n    String valueJsonString = FirestoreProto2Json.DEFAULT.valueToJsonString(firestoreEventData);\n    logger.info(\"Value: \" + valueJsonString);\n\n    // Convert the old value to JSON\n    String oldVauleJsonString = FirestoreProto2Json.DEFAULT.oldValueToJsonString(firestoreEventData);\n    logger.info(\"Old Value: \" + oldVauleJsonString);\n  }\n}\n```\n\nA GSON JsonObject can be returned instead of a String which may be useful for additional manipulation.\n\n```java\nJsonObject valueJsonObject = FirestoreProto2Json.DEFAULT.valueToJsonObject(firestoreEventData);\nJsonObject oldValueJsonObject = FirestoreProto2Json.DEFAULT.oldValueToJsonObject(firestoreEventData);\n```\n\nAdditional functions are available for converting from the `byte[]` of the Protocol Buffer for the [DocumentEventData](https://github.com/googleapis/google-cloudevents/blob/main/proto/google/events/cloud/firestore/v1/data.proto) or a base64 encoded version as well.\n\n## Field Conversions\n\nFirestore's [supported data types](https://cloud.google.com/firestore/docs/concepts/data-types) are converted to JSON using the following rules.\n\n| Firestore Data Type   | JSON Data Type                 | Example                                                                     |\n| --------------------- | ------------------------------ | --------------------------------------------------------------------------- |\n| Array                 | JSON Array                     | `{\"foo\": [1, 2, 3]}`                                                        |\n| Boolean               | Boolean                        | `{\"foo\": true}`                                                             |\n| Bytes                 | JSON Object with Base64 String | `{\"foo\": {\"_byteString\": \"ZXhhbXBsZQ==\"} }`                                 |\n| Date and Time         | String                         | `{\"foo\": \"2024-02-26T23:18:55.296Z\"}`                                       |\n| Floating Point number | Number                         | `{\"foo\": 12.34}`                                                            |\n| Geographical point    | JSON Object with Numbers       | `{\"foo\": {\"latitude\": 36.74050912505929,\"longitude\": -57.83434128116206} }` |\n| Integer               | Number                         | `{\"foo\": 123}`                                                              |\n| Map                   | JSON Object                    | `{\"foo\": {\"bar\": 123} }`                                                    |\n| Null                  | Null                           | `{\"foo\": null}`                                                             |\n| Reference             | String                         | `{\"foo\": \"projects/example/databases/(default)/documents/example/record\"}`  |\n| Text string           | String                         | `{\"foo\": \"bar\"}`                                                            |\n\n### Assumptions and Limitations\n\nThe likely reason Google does not provide this functionality is because there is not a single clean conversion between the Protocol Buffer representation of the document and the JSON representation expected by the application.\n\nTherefore, this library makes a few assumptions regarding the structure of the JSON payload to be generated. For example the formatting of the timestamp field into a string, there are multiple formats that could be used to represent the date.\n\nThe field types with ambiguous conversions can be customized to meet the requirements of the specific use case if necessary.\n\n### Bytes Field\n\nBinary data stored in an attribute in Firestore when represented in JSON will need to be encoded. The encoding used is base64 with the field being stored in a JSON Object with the attribute \"\\_byteString\"\n\n```json\n{\n  \"foo\": {\n    \"_byteString\": \"ZXhhbXBsZQ==\"\n  }\n}\n```\n\nThis conversion can be customized by extending the ValueMapperBytes class. A custom FirestoreProto2Json can then be used instead of the default. The following is an example where the text is encoded as hexidecimal and directly assigned to the attribute name.\n\n```java\nFirestoreProto2Json firestoreProto2Json =\n        FirestoreProto2Json.builder().valueMapperBytes(new ValueMapperBytes() {\n            @Override\n            public void convert(JsonObject jsonObject, String key, byte[] bytes) {\n                jsonObject.addProperty(key, HexFormat.of().formatHex(bytes));\n            }\n\n            @Override\n            public void convert(JsonArray jsonArray, byte[] bytes) {\n                jsonArray.add(HexFormat.of().formatHex(bytes));\n            }\n        }).build();\n```\n\n### GeoPoint Field\n\nGoogle discourages the use of the GeoPoint type, but it is fully supported. The default mapping being a JSON Object with the latitude and longitude as attribute. The mapping can be overridden by implementing the `ValueMapperGeoPoint` class.\n\n```json\n{\n  \"foo\": {\n    \"latitude\": 36.74050912505929,\n    \"longitude\": -57.83434128116206\n  }\n}\n```\n\n### Timestamp Field\n\nThe most likely field whose format may need to be overridden is the Timestamp field. The default behavior is to encode the timestamp as \"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'\" in the UTC timezone.\n\nWhile `ValueMapperTimestamp` can be overridden to fully customize the conversion `ValueMapperTimestampDefault` provides additional constructors that allow the format and timezone to be specified to simplify customization. For example, the follow customization formats the time but only to the whole second.\n\n```java\nFirestoreProto2Json converter = FirestoreProto2Json.builder()\n        .valueMapperTimestamp(\n                new ValueMapperTimestampDefault(\"yyyy-MM-dd'T'HH:mm:ss'Z'\", ZoneOffset.UTC))\n        .build();\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funitvectory-labs%2Ffirestoreproto2json","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Funitvectory-labs%2Ffirestoreproto2json","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funitvectory-labs%2Ffirestoreproto2json/lists"}