Skip to content

Commit

Permalink
TEMPORARY FIX: allow "values" to by of type array or object in input api
Browse files Browse the repository at this point in the history
- this is to conform with the old api
- the old api accepted the value (no error), but didn't store what was expected: "value": [1,2,true] stored "value": "true" ...
- here, at least we both accept AND store the correct value
  • Loading branch information
derlin committed Sep 30, 2020
1 parent 0ae9eaa commit cef8cc5
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 2 deletions.
6 changes: 4 additions & 2 deletions src/main/kotlin/ch/derlin/bbdata/input/InputController.kt
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,10 @@ class InputController(
@PostMapping("objects/values")
@Operation(description = "Submit new measures. " +
"Each objectId/timestamp couple must be unique, both in the body and the database. Hence, any duplicate will make the request fail. " +
"If you omit to provide a timestamp for any measure, it will be added automatically (server time). " +
"This request is *atomic*: either *all* measures are valid and saved, or none. ")
"This request is *atomic*: either *all* measures are valid and saved, or none. " +
"If you omit to provide a timestamp for any measure, it will be added automatically (server time).<br><br>" +
"In general, it is better to always enclose the value in quotes. DO NOT send arrays or objects without enclosing quotes, " +
"but serialize them on the collector in order to avoid surprises !")
fun postNewMeasures(@Valid @NotNull @RequestBody rawMeasures: ValidatedList<NewValue>,
@RequestParam("simulate", defaultValue = "false") sim: Boolean): List<NewValueAugmented> {

Expand Down
2 changes: 2 additions & 0 deletions src/main/kotlin/ch/derlin/bbdata/input/NewValue.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package ch.derlin.bbdata.input
import ch.derlin.bbdata.common.cassandra.RawValue
import ch.derlin.bbdata.common.cassandra.RawValuePK
import ch.derlin.bbdata.common.truncate
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import org.joda.time.DateTime
import org.joda.time.YearMonth
import javax.validation.constraints.Min
Expand Down Expand Up @@ -30,6 +31,7 @@ data class NewValue(

@field:NotNull
@field:NotEmpty
@field:JsonDeserialize(using = RawStringDeserializer::class)
var value: String? = null,

@field:Size(max = 1024, message = "too long. Maximum set to 1024.")
Expand Down
43 changes: 43 additions & 0 deletions src/main/kotlin/ch/derlin/bbdata/input/RawStringDeserializer.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package ch.derlin.bbdata.input

import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.ObjectMapper


/**
*
* Problem: in the old api, people got used to send arrays or objects as "value",
* while new version is expecting a string.
*
* This mapper always deserialize into strings.
* The behavior is the same for values enclosed in quotes or basic values, it only changes for
* raw arrays ("value": [...]) or objects (e.g. "value": {...}).
*
* Example:
* - "value": [1, 2, false ] => "[1,2,false]"
* - "value": {"a": 1, "b" : "x"} => "{\"a\":1,\"b\":\"x\"}",
* - "value": "[1, 2,false]" => "[1, 2,false]"
* - "value": 1 => "1.0"
*
* BEWARE: if not using quotes, the array or object MUST BE A CORRECT json array/object
*
* date: 30.09.20
* @author Lucy Linder <[email protected]>
*/
class RawStringDeserializer : JsonDeserializer<String?>() {

// basic objectMapper: no prettyPrint, nothing...
private val objectMapper = ObjectMapper()

override fun deserialize(p: JsonParser, ctxt: DeserializationContext?): String? {
// use default objectMapper for deserialization, so we keep the usual settings
val node: JsonNode = (if (p.codec is ObjectMapper) p.codec else objectMapper).readTree(p)
// Do not use the default objectMapper for serialization
// since it may be configured with prettyPrint = true
val ret = if (node.isTextual) node.asText() else objectMapper.writeValueAsString(node)
return ret
}
}

0 comments on commit cef8cc5

Please sign in to comment.