From cfa87e39abd7dfe75dcb3267e1259b32401dd70e Mon Sep 17 00:00:00 2001 From: Jesse S Date: Wed, 6 Sep 2023 10:11:29 -0700 Subject: [PATCH] APPS-884 Fix GeoJSON insert (#145) * docs: APPS-882 Clarify providing GeoJSON bin types * fix: APPS-884 GeoJSON bins are inserted as Aerospike Maps --------- Co-authored-by: Eugene R. --- Makefile | 4 + README.md | 4 +- docs/data-formats.md | 46 ++-- docs/installation-and-config.md | 2 +- docs/operate.md | 2 +- .../controllers/KeyValueController.java | 196 ++++++------------ .../restclient/util/APIParamDescriptors.java | 2 +- .../restclient/util/RequestBodyExamples.java | 2 +- .../util/converters/BinConverter.java | 2 +- .../restclient/RecordPostCorrectTests.java | 21 +- 10 files changed, 128 insertions(+), 153 deletions(-) diff --git a/Makefile b/Makefile index f8e2a009..7f88103e 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,10 @@ package: clean validatedocs build build: ./gradlew build -x test +.PHONY: run +run: + ./gradlew bootRun + .PHONY: clean clean: echo $(VERSION) diff --git a/README.md b/README.md index 724d072b..fa9c6789 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ here [Aerospike REST Gateway API Documentation](https://docs.aerospike.com/apido ## Prerequisites -* Java 17 or later for REST Gateway 2.0 and newer. Java 8 or later for REST Gateway 1.11 and earlier. +* Java 17 or later for REST Gateway 2.0 and newer. Java 8 or later for REST Gateway 1.11 and earlier. * Aerospike Server version 4.9+ ## Installation @@ -85,7 +85,7 @@ languages. 1. Go to [Swagger Editor](https://editor.swagger.io/). 2. Import the Aerospike REST - Client [openapi.json](https://github.com/aerospike/aerospike-rest-gateway/blob/master/docs/openapi.json) file. + Client [openapi.json](https://aerospike.github.io/aerospike-rest-gateway/openapi.json) file. 3. Click on Generate Server/Generate Client and choose the desired language/framework. 4. A .zip file that contains all the necessary files for a server/client will be downloaded. diff --git a/docs/data-formats.md b/docs/data-formats.md index ed606554..e6f27db7 100644 --- a/docs/data-formats.md +++ b/docs/data-formats.md @@ -1,4 +1,4 @@ -# Rest Gateway Data Formats +# REST Gateway Data Formats API Requests which involve sending data can use the `JSON`, or `MessagePack` formats. By default JSON will be assumed. To use `MessagePack`, set the `Content-Type` header to ``"application/msgpack"``. Similarly @@ -11,13 +11,9 @@ For many uses `JSON` is a simpler and completely valid option. It provides simpl Key Value operations are being used, and neither Maps with non string keys, Bytes nor GeoJSON are required, then `JSON` will work completely with the Aerospike data model. -**Note**: In version 1.0 GeoJSON and ByteArray bin values are supported. A GeoJSON map with the keys "type" and " -coordinates" will automatically be understood as a GeoJSON type. Similarly, a ByteArray can be provided using a map with -the keys "type" -and "value" where the type is "byteArray" and the value is a base64 encoded string. One caveat is GeoJSON and ByteArrays -can not be nested in CDTs. +**Note**: GeoJSON and ByteArrays can not be nested in CDTs. -Ex. GeoJSON +In 2.0.4, a GeoJSON map with the keys "type" and "coordinates" will automatically be understood as a GeoJSON type. ```javascript { @@ -26,7 +22,21 @@ Ex. GeoJSON } ``` -Ex. ByteArray +In version prior to 2.0.4, a GeoJSON object can be provided by sending a base64 encoded GeoJSON string. +Base64 encoding the following string `{"type": "Point", "coordinates": [1.123, 4.156]}` results +in `eyJ0eXBlIjogIlBvaW50IiwgImNvb3JkaW5hdGVzIjogWzEuMTIzLCA0LjE1Nl19Cg==`. +To write the GeoJSON object use + +```javascript +{ + "type": "GEO_JSON", + "value": "eyJ0eXBlIjogIlBvaW50IiwgImNvb3JkaW5hdGVzIjogWzEuMTIzLCA0LjE1Nl19Cg==" +} +``` + +Similarly, starting in 1.0.0 a ByteArray can be provided using a map with +the keys "type" +and "value" where the type is "byteArray" and the value is a base64 encoded string. ```javascript { @@ -57,17 +67,17 @@ differentiate a normal string from GeoJSON. For example to write a bin map usable by the API with a GeoJSON value utilizing Python. ```python -# Python 2.7 -import msgpack -packed_geojson = msgpack.ExtType(23, "{\"coordinates\": [-122.0, 37.5], \"type\": \"Point\"}") -packed_bins = {u'geo_bin': packed_geojson} -mp_bins = msgpack.packb(packed_bins) + # Python 2.7 + import msgpack + packed_geojson = msgpack.ExtType(23, "{\"coordinates\": [-122.0, 37.5], \"type\": \"Point\"}") + packed_bins = {u'geo_bin': packed_geojson} + mp_bins = msgpack.packb(packed_bins) ``` Or with Java ```java -MessageBufferPacker packer=new MessagePack.PackerConfig().newBufferPacker(); + MessageBufferPacker packer=new MessagePack.PackerConfig().newBufferPacker(); String geoString="{\"coordinates\": [-122.0, 37.5], \"type\": \"Point\"}"; packer.packMapHeader(1); packer.packString("geo_bin"); @@ -78,13 +88,13 @@ MessageBufferPacker packer=new MessagePack.PackerConfig().newBufferPacker(); Bytes are a standard Message Pack type. Here is an example of creating a Bin Map to be used with the API ```python -# Python 2.7 -test_bytes = bytearray([1,2,3]) -mp_bytes_bins = msgpack.packb({u'my_bytes': test_bytes}, use_bin_type=True) + # Python 2.7 + test_bytes = bytearray([1,2,3]) + mp_bytes_bins = msgpack.packb({u'my_bytes': test_bytes}, use_bin_type=True) ``` ```java -byte[]testBytes={1,2,3}; + byte[]testBytes={1,2,3}; MessageBufferPacker packer=new MessagePack.PackerConfig().newBufferPacker(); packer.packMapHeader(1); diff --git a/docs/installation-and-config.md b/docs/installation-and-config.md index dc4f4dd8..362cc66e 100644 --- a/docs/installation-and-config.md +++ b/docs/installation-and-config.md @@ -19,7 +19,7 @@ make build * Run Locally during development: ```sh -./gradlew bootRun +make run ``` ### Run using a Jar file diff --git a/docs/operate.md b/docs/operate.md index f8c657a4..3a2dc368 100644 --- a/docs/operate.md +++ b/docs/operate.md @@ -2,7 +2,7 @@ # DEPRECATED - Operatation documentation is now imbedded in the swagger documentation. +# Operation documentation is now embedded in the swagger documentation as of 2.0.1 # Rest Gateway Operations diff --git a/src/main/java/com/aerospike/restclient/controllers/KeyValueController.java b/src/main/java/com/aerospike/restclient/controllers/KeyValueController.java index 628b8950..6bc68a4b 100644 --- a/src/main/java/com/aerospike/restclient/controllers/KeyValueController.java +++ b/src/main/java/com/aerospike/restclient/controllers/KeyValueController.java @@ -60,7 +60,7 @@ public class KeyValueController { public static final String NAMESPACE_NOTES = "Namespace for the record; equivalent to database name."; public static final String SET_NOTES = "Set for the record; equivalent to database table."; public static final String USERKEY_NOTES = "Userkey for the record."; - public static final String STORE_BINS_NOTES = "Bins to be stored in the record. This is a mapping from a string bin name to a value. " + "Value can be a String, integer, floating point number, list, map, bytearray, or GeoJSON value. Bytearrays and GeoJSON can " + "only be sent using MessagePack\n " + "example: {\"bin1\":5, \"bin2\":\"hello\", \"bin3\": [1,2,3], \"bin4\": {\"one\": 1}}"; + public static final String STORE_BINS_NOTES = "Bins to be stored in the record. This is a mapping from a string bin name to a value. " + "Value can be a String, integer, floating point number, list, map, bytearray, or GeoJSON value. For more information on data formats, older APIs, and msgpack: https://github.com/aerospike/aerospike-rest-gateway/blob/master/docs/data-formats.md"; public static final String GET_RECORD_NOTES = "Return the metadata and bins for a record."; public static final String UPDATE_RECORD_NOTES = "Merge the provided bins into the record."; public static final String CREATE_RECORD_NOTES = "Create a new record with the provided bins into the record."; @@ -101,19 +101,16 @@ public class KeyValueController { @ASRestClientParams.ASRestClientRecordBinsQueryParam @ASRestClientPolicyQueryParams public RestClientRecord getRecordNamespaceSetKey(@Parameter( - description = NAMESPACE_NOTES, - required = true + description = NAMESPACE_NOTES, required = true ) @PathVariable(value = "namespace") String namespace, @Parameter(description = SET_NOTES, required = true) @PathVariable( value = "set" ) String set, @Parameter( - description = USERKEY_NOTES, - required = true + description = USERKEY_NOTES, required = true ) @PathVariable(value = "key") String key, @Parameter(hidden = true) @RequestParam MultiValueMap requestParams, @RequestHeader( - value = "Authorization", - required = false + value = "Authorization", required = false ) String basicAuth) { String[] bins = RequestParamHandler.getBinsFromMap(requestParams); @@ -150,16 +147,13 @@ public RestClientRecord getRecordNamespaceSetKey(@Parameter( @ASRestClientParams.ASRestClientRecordBinsQueryParam @ASRestClientPolicyQueryParams public RestClientRecord getRecordNamespaceKey(@Parameter( - description = NAMESPACE_NOTES, - required = true + description = NAMESPACE_NOTES, required = true ) @PathVariable(value = "namespace") String namespace, @Parameter( - description = USERKEY_NOTES, - required = true + description = USERKEY_NOTES, required = true ) @PathVariable(value = "key") String key, @Parameter(hidden = true) @RequestParam MultiValueMap requestParams, @RequestHeader( - value = "Authorization", - required = false + value = "Authorization", required = false ) String basicAuth) { String[] bins = RequestParamHandler.getBinsFromMap(requestParams); @@ -205,19 +199,15 @@ public RestClientRecord getRecordNamespaceKey(@Parameter( @ASRestClientParams.ASRestClientKeyTypeQueryParam @ASRestClientWritePolicyQueryParams public void deleteRecordNamespaceSetKey(@Parameter( - description = NAMESPACE_NOTES, - required = true + description = NAMESPACE_NOTES, required = true ) @PathVariable(value = "namespace") String namespace, @Parameter( - description = SET_NOTES, - required = true + description = SET_NOTES, required = true ) @PathVariable(value = "set") String set, @Parameter( - description = USERKEY_NOTES, - required = true + description = USERKEY_NOTES, required = true ) @PathVariable(value = "key") String key, @Parameter(hidden = true) @RequestParam Map requestParams, @RequestHeader( - value = "Authorization", - required = false + value = "Authorization", required = false ) String basicAuth) { RecordKeyType keyType = RequestParamHandler.getKeyTypeFromMap(requestParams); @@ -257,11 +247,9 @@ public void deleteRecordNamespaceSetKey(@Parameter( @ASRestClientParams.ASRestClientKeyTypeQueryParam @ASRestClientWritePolicyQueryParams public void deleteRecordNamespaceKey(@Parameter( - description = NAMESPACE_NOTES, - required = true + description = NAMESPACE_NOTES, required = true ) @PathVariable(value = "namespace") String namespace, @Parameter( - description = USERKEY_NOTES, - required = true + description = USERKEY_NOTES, required = true ) @PathVariable(value = "key") String key, @Parameter(hidden = true) @RequestParam Map requestParams, @RequestHeader(value = "Authorization", required = false) String basicAuth) { @@ -310,26 +298,20 @@ public void deleteRecordNamespaceKey(@Parameter( @ASRestClientParams.ASRestClientKeyTypeQueryParam @ASRestClientWritePolicyQueryParams public void replaceRecordNamespaceSetKey(@Parameter( - description = NAMESPACE_NOTES, - required = true + description = NAMESPACE_NOTES, required = true ) @PathVariable(value = "namespace") String namespace, @Parameter( - description = SET_NOTES, - required = true + description = SET_NOTES, required = true ) @PathVariable(value = "set") String set, @Parameter(description = USERKEY_NOTES, required = true) @PathVariable( value = "key" ) String key, @io.swagger.v3.oas.annotations.parameters.RequestBody( - description = STORE_BINS_NOTES, - required = true, - content = @Content( - examples = @ExampleObject( - name = RequestBodyExamples.BINS_NAME, - value = RequestBodyExamples.BINS_VALUE - ) + description = STORE_BINS_NOTES, required = true, content = @Content( + examples = @ExampleObject( + name = RequestBodyExamples.BINS_NAME, value = RequestBodyExamples.BINS_VALUE ) + ) ) @RequestBody Map bins, @Parameter(hidden = true) @RequestParam Map requestParams, @RequestHeader( - value = "Authorization", - required = false + value = "Authorization", required = false ) String basicAuth) { RecordKeyType keyType = RequestParamHandler.getKeyTypeFromMap(requestParams); @@ -373,10 +355,10 @@ public void replaceRecordNamespaceSetKey(@Parameter( public void replaceRecordNamespaceSetKeyMP(@PathVariable(value = "namespace") String namespace, @PathVariable(value = "set") String set, @PathVariable(value = "key") String key, InputStream dataStream, - @RequestParam Map requestParams, @RequestHeader( - value = "Authorization", - required = false - ) String basicAuth) { + @Parameter(hidden = true) @RequestParam Map requestParams, + @RequestHeader( + value = "Authorization", required = false + ) String basicAuth) { RecordKeyType keyType = RequestParamHandler.getKeyTypeFromMap(requestParams); WritePolicy policy = RequestParamHandler.getWritePolicy(requestParams, RecordExistsAction.REPLACE_ONLY); @@ -420,20 +402,15 @@ public void replaceRecordNamespaceSetKeyMP(@PathVariable(value = "namespace") St @ASRestClientParams.ASRestClientKeyTypeQueryParam @ASRestClientWritePolicyQueryParams public void replaceRecordNamespaceKey(@Parameter( - description = NAMESPACE_NOTES, - required = true + description = NAMESPACE_NOTES, required = true ) @PathVariable(value = "namespace") String namespace, @Parameter( - description = USERKEY_NOTES, - required = true + description = USERKEY_NOTES, required = true ) @PathVariable(value = "key") String key, @io.swagger.v3.oas.annotations.parameters.RequestBody( - description = STORE_BINS_NOTES, - required = true, - content = @Content( - examples = @ExampleObject( - name = RequestBodyExamples.BINS_NAME, - value = RequestBodyExamples.BINS_VALUE - ) + description = STORE_BINS_NOTES, required = true, content = @Content( + examples = @ExampleObject( + name = RequestBodyExamples.BINS_NAME, value = RequestBodyExamples.BINS_VALUE ) + ) ) @RequestBody Map bins, @Parameter(hidden = true) @RequestParam Map requestParams, @RequestHeader(value = "Authorization", required = false) String basicAuth) { @@ -454,8 +431,7 @@ public void replaceRecordNamespaceKey(@Parameter( public void replaceRecordNamespaceKeyMP(@PathVariable(value = "namespace") String namespace, @PathVariable(value = "key") String key, InputStream dataStream, @RequestParam Map requestParams, @RequestHeader( - value = "Authorization", - required = false + value = "Authorization", required = false ) String basicAuth) { RecordKeyType keyType = RequestParamHandler.getKeyTypeFromMap(requestParams); @@ -505,27 +481,20 @@ public void replaceRecordNamespaceKeyMP(@PathVariable(value = "namespace") Strin @ASRestClientParams.ASRestClientKeyTypeQueryParam @ASRestClientWritePolicyQueryParams public void createRecordNamespaceSetKey(@Parameter( - description = NAMESPACE_NOTES, - required = true + description = NAMESPACE_NOTES, required = true ) @PathVariable(value = "namespace") String namespace, @Parameter( - description = SET_NOTES, - required = true + description = SET_NOTES, required = true ) @PathVariable(value = "set") String set, @Parameter( - description = USERKEY_NOTES, - required = true + description = USERKEY_NOTES, required = true ) @PathVariable(value = "key") String key, @io.swagger.v3.oas.annotations.parameters.RequestBody( - description = STORE_BINS_NOTES, - required = true, - content = @Content( - examples = @ExampleObject( - name = RequestBodyExamples.BINS_NAME, - value = RequestBodyExamples.BINS_VALUE - ) + description = STORE_BINS_NOTES, required = true, content = @Content( + examples = @ExampleObject( + name = RequestBodyExamples.BINS_NAME, value = RequestBodyExamples.BINS_VALUE ) + ) ) @RequestBody Map bins, @Parameter(hidden = true) @RequestParam Map requestParams, @RequestHeader( - value = "Authorization", - required = false + value = "Authorization", required = false ) String basicAuth) { RecordKeyType keyType = RequestParamHandler.getKeyTypeFromMap(requestParams); @@ -546,8 +515,7 @@ public void createRecordNamespaceSetKeyMP(@PathVariable(value = "namespace") Str @PathVariable(value = "set") String set, @PathVariable(value = "key") String key, InputStream dataStream, @RequestParam Map requestParams, @RequestHeader( - value = "Authorization", - required = false + value = "Authorization", required = false ) String basicAuth) { RecordKeyType keyType = RequestParamHandler.getKeyTypeFromMap(requestParams); @@ -592,20 +560,15 @@ public void createRecordNamespaceSetKeyMP(@PathVariable(value = "namespace") Str @ASRestClientParams.ASRestClientKeyTypeQueryParam @ASRestClientWritePolicyQueryParams public void createRecordNamespaceKey(@Parameter( - description = NAMESPACE_NOTES, - required = true + description = NAMESPACE_NOTES, required = true ) @PathVariable(value = "namespace") String namespace, @Parameter( - description = USERKEY_NOTES, - required = true + description = USERKEY_NOTES, required = true ) @PathVariable(value = "key") String key, @io.swagger.v3.oas.annotations.parameters.RequestBody( - description = STORE_BINS_NOTES, - required = true, - content = @Content( - examples = @ExampleObject( - name = RequestBodyExamples.BINS_NAME, - value = RequestBodyExamples.BINS_VALUE - ) + description = STORE_BINS_NOTES, required = true, content = @Content( + examples = @ExampleObject( + name = RequestBodyExamples.BINS_NAME, value = RequestBodyExamples.BINS_VALUE ) + ) ) @RequestBody Map bins, @Parameter(hidden = true) @RequestParam Map requestParams, @RequestHeader(value = "Authorization", required = false) String basicAuth) { @@ -675,27 +638,20 @@ public void createRecordNamespaceKeyMP(@PathVariable(value = "namespace") String @ASRestClientParams.ASRestClientKeyTypeQueryParam @ASRestClientWritePolicyQueryParams public void updateRecordNamespaceSetKey(@Parameter( - description = NAMESPACE_NOTES, - required = true + description = NAMESPACE_NOTES, required = true ) @PathVariable(value = "namespace") String namespace, @Parameter( - description = SET_NOTES, - required = true + description = SET_NOTES, required = true ) @PathVariable(value = "set") String set, @Parameter( - description = USERKEY_NOTES, - required = true + description = USERKEY_NOTES, required = true ) @PathVariable(value = "key") String key, @io.swagger.v3.oas.annotations.parameters.RequestBody( - description = STORE_BINS_NOTES, - required = true, - content = @Content( - examples = @ExampleObject( - name = RequestBodyExamples.BINS_NAME, - value = RequestBodyExamples.BINS_VALUE - ) + description = STORE_BINS_NOTES, required = true, content = @Content( + examples = @ExampleObject( + name = RequestBodyExamples.BINS_NAME, value = RequestBodyExamples.BINS_VALUE ) + ) ) @RequestBody Map bins, @Parameter(hidden = true) @RequestParam Map requestParams, @RequestHeader( - value = "Authorization", - required = false + value = "Authorization", required = false ) String basicAuth) { RecordKeyType keyType = RequestParamHandler.getKeyTypeFromMap(requestParams); @@ -716,8 +672,7 @@ public void updateRecordNamespaceSetKeyMP(@PathVariable(value = "namespace") Str @PathVariable(value = "set") String set, @PathVariable(value = "key") String key, InputStream dataStream, @RequestParam Map requestParams, @RequestHeader( - value = "Authorization", - required = false + value = "Authorization", required = false ) String basicAuth) { RecordKeyType keyType = RequestParamHandler.getKeyTypeFromMap(requestParams); @@ -762,20 +717,15 @@ public void updateRecordNamespaceSetKeyMP(@PathVariable(value = "namespace") Str @ASRestClientParams.ASRestClientKeyTypeQueryParam @ASRestClientWritePolicyQueryParams public void updateRecordNamespaceKey(@Parameter( - description = NAMESPACE_NOTES, - required = true + description = NAMESPACE_NOTES, required = true ) @PathVariable(value = "namespace") String namespace, @Parameter( - description = USERKEY_NOTES, - required = true + description = USERKEY_NOTES, required = true ) @PathVariable(value = "key") String key, @io.swagger.v3.oas.annotations.parameters.RequestBody( - description = STORE_BINS_NOTES, - required = true, - content = @Content( - examples = @ExampleObject( - name = RequestBodyExamples.BINS_NAME, - value = RequestBodyExamples.BINS_VALUE - ) + description = STORE_BINS_NOTES, required = true, content = @Content( + examples = @ExampleObject( + name = RequestBodyExamples.BINS_NAME, value = RequestBodyExamples.BINS_VALUE ) + ) ) @RequestBody Map bins, @Parameter(hidden = true) @RequestParam Map requestParams, @RequestHeader(value = "Authorization", required = false) String basicAuth) { @@ -830,20 +780,15 @@ public void updateRecordNamespaceKeyMP(@PathVariable(value = "namespace") String produces = {"application/json", "application/msgpack"} ) public void recordExistsNamespaceSetKey(@Parameter( - description = NAMESPACE_NOTES, - required = true + description = NAMESPACE_NOTES, required = true ) @PathVariable(value = "namespace") String namespace, @Parameter( - description = SET_NOTES, - required = true + description = SET_NOTES, required = true ) @PathVariable(value = "set") String set, @Parameter( - description = USERKEY_NOTES, - required = true + description = USERKEY_NOTES, required = true ) @PathVariable(value = "key") String key, @Parameter(hidden = true) HttpServletResponse res, @Parameter( - name = "keytype", - description = APIDescriptors.KEYTYPE_NOTES + name = "keytype", description = APIDescriptors.KEYTYPE_NOTES ) @RequestParam(value = "keytype", required = false) RecordKeyType keyType, @RequestHeader( - value = "Authorization", - required = false + value = "Authorization", required = false ) String basicAuth) { AuthDetails authDetails = HeaderHandler.extractAuthDetails(basicAuth); @@ -882,14 +827,11 @@ public void recordExistsNamespaceSetKey(@Parameter( produces = {"application/json", "application/msgpack"} ) public void recordExistsNamespaceKey(@Parameter( - description = NAMESPACE_NOTES, - required = true + description = NAMESPACE_NOTES, required = true ) @PathVariable(value = "namespace") String namespace, @Parameter( - description = USERKEY_NOTES, - required = true + description = USERKEY_NOTES, required = true ) @PathVariable(value = "key") String key, @Parameter(hidden = true) HttpServletResponse res, @Parameter( - name = "keytype", - description = APIDescriptors.KEYTYPE_NOTES + name = "keytype", description = APIDescriptors.KEYTYPE_NOTES ) @RequestParam(value = "keytype", required = false) RecordKeyType keyType, @RequestHeader(value = "Authorization", required = false) String basicAuth) { diff --git a/src/main/java/com/aerospike/restclient/util/APIParamDescriptors.java b/src/main/java/com/aerospike/restclient/util/APIParamDescriptors.java index c316e74c..537ea0da 100644 --- a/src/main/java/com/aerospike/restclient/util/APIParamDescriptors.java +++ b/src/main/java/com/aerospike/restclient/util/APIParamDescriptors.java @@ -20,7 +20,7 @@ public class APIParamDescriptors { public static final String NAMESPACE_NOTES = "Namespace for the record; equivalent to database name."; public static final String SET_NOTES = "Set for the record; equivalent to database table."; public static final String USERKEY_NOTES = "Userkey for the record."; - public static final String STORE_BINS_NOTES = "Bins to be stored in the record. This is a mapping from a string bin name to a value. " + "Value can be a String, integer, floating point number, list, map, bytearray, or GeoJSON value. Bytearrays and GeoJSON can " + "only be sent using MessagePack\n " + "example: {\"bin1\":5, \"bin2\":\"hello\", \"bin3\": [1,2,3], \"bin4\": {\"one\": 1}}"; + public static final String STORE_BINS_NOTES = "Bins to be stored in the record. This is a mapping from a string bin name to a value. " + "Value can be a String, integer, floating point number, list, map, bytearray, or GeoJSON value."; public static final String QUERY_PARTITION_BEGIN_NOTES = "Start partition id (0 - 4095)"; public static final String QUERY_PARTITION_COUNT_NOTES = "Number of partitions"; diff --git a/src/main/java/com/aerospike/restclient/util/RequestBodyExamples.java b/src/main/java/com/aerospike/restclient/util/RequestBodyExamples.java index 86c905e8..5d1f5d0c 100644 --- a/src/main/java/com/aerospike/restclient/util/RequestBodyExamples.java +++ b/src/main/java/com/aerospike/restclient/util/RequestBodyExamples.java @@ -32,5 +32,5 @@ public class RequestBodyExamples { // key value public static final String BINS_NAME = "Bins request body example"; - public static final String BINS_VALUE = "{\"bin1\":5, \"bin2\":\"hello\", \"bin3\": [1,2,3], \"bin4\": {\"one\": 1}}"; + public static final String BINS_VALUE = "{\"intBin\":5, \"strBin\":\"hello\", \"listBin\": [1,2,3], \"dictBin\": {\"one\": 1}, \"geoJsonBin\": {\"type\": \"Point\", \"coordinates\": [1.123, 4.156]}, \"byteArrayBin\": {\"type\": \"BYTE_ARRAY\", \"value\": \"YWVyb3NwaWtlCg==\"}}"; } diff --git a/src/main/java/com/aerospike/restclient/util/converters/BinConverter.java b/src/main/java/com/aerospike/restclient/util/converters/BinConverter.java index c2050e13..371c4cbf 100644 --- a/src/main/java/com/aerospike/restclient/util/converters/BinConverter.java +++ b/src/main/java/com/aerospike/restclient/util/converters/BinConverter.java @@ -116,7 +116,7 @@ public static Bin binFromObject(String key, Object value) { } private static boolean isGeoJSON(Map value) { - return (isGeoJSONGeometry(value) && isGeoJSONFeature(value)); + return (isGeoJSONGeometry(value) || isGeoJSONFeature(value)); } // Only checks keys to determine if is supported geojson. diff --git a/src/test/java/com/aerospike/restclient/RecordPostCorrectTests.java b/src/test/java/com/aerospike/restclient/RecordPostCorrectTests.java index bee8d114..26c383e1 100644 --- a/src/test/java/com/aerospike/restclient/RecordPostCorrectTests.java +++ b/src/test/java/com/aerospike/restclient/RecordPostCorrectTests.java @@ -255,7 +255,7 @@ public void PostByteArray() throws Exception { } @Test - public void PostGeoJson() throws Exception { + public void PostBase64EncodedGeoJson() throws Exception { Map binMap = new HashMap<>(); Map geoJson = new HashMap<>(); String geoStr = "{\"type\": \"Point\", \"coordinates\": [-80.604333, 28.608389]}"; @@ -270,6 +270,25 @@ public void PostGeoJson() throws Exception { Assert.assertEquals(((Value.GeoJSONValue) record.bins.get("geo_json")).getObject(), geoStr); } + @Test + public void PostGeoJson() throws Exception { + Map binMap = new HashMap<>(); + Map geoJson = new HashMap<>(); + List coordinates = new ArrayList<>(); + coordinates.add(-80.604333); + coordinates.add(28.608389); + String geoStr = "{\"coordinates\":[-80.604333,28.608389],\"type\":\"Point\"}"; + geoJson.put("coordinates", coordinates); + geoJson.put("type", "Point"); + + binMap.put("geo_json", geoJson); + + postPerformer.perform(mockMVC, testEndpoint, binMap); + + Record record = client.get(null, this.testKey); + Assert.assertEquals(((Value.GeoJSONValue) record.bins.get("geo_json")).getObject(), geoStr); + } + @Test public void PostBoolean() throws Exception { Map binMap = new HashMap<>();