2
votes

In a Spring boot 2.2.X app, I have a rest endpoint that accepts any simple Json object. The java type used to accommodate this is Map<String,Object>.

Example input:

{
   "productId":123,
   "type": Perishable
   "location":"\\server\path\to\images\123.png"
}

I'm facing unexpected behavior with the image file location String. In my controller, when I inspect the contents of the Map<String,Object> I see the following value. Some slashes are stripped, and some aren't. (I used a custom mapper to allow slashes at all places in json -> JsonParser.Feature "allow_backslash_escaping_any_character").

@PostMapping(value = "products}")
public UUID persistProduct(@RequestBody @NotNull Map<String,Object> parameters){
    return this.productService.persistProduct(parameters);
}

Controller after deserialization

Note that the first two backslashes are rendered as one, but it's actually still two backslashes. My app now deserialized this Map back to a json string, to persist it in the database. This is done by using standard Jackson classes:

public static String toJsonString(Object o){
    try{
        return new ObjectMapper().registerModule(new JavaTimeModule()).writer().writeValueAsString(o);
    }
    catch (JsonProcessingException e){
        throw new UncheckedWrapperException("Converting an object to a JSON literal string", e);
    }
}

Once persisted to the database the entire Json becomes:

enter image description here

If I now change the input by consistently escaping every backslash character with another backslash:

{
   "productId":123,
   "type": Perishable
   "location":"\\\\server\\path\\to\\images\\123.png"
}

The result in the controller looks promising, but the database record now contains ALL slashes (so the escaping suddenly has no effect, which means to many slashes are stored?)

controller

database

I don't really understand this behavior. Is there a way to tell Spring or Jackson to store in the database EXACTLY what is being entered in the input json? I obviously would also like to avoid jeopardizing the endpoint's security by simply disabling this.

Hey! Can you show a bit of the code? Would be extremely helpful. The controller and the way you serialize would be nice! - Jason
@Jason The controller is very straigthforward; I added it to the question. The deserialization feature to allow backslashes was added using a property in the property file. The serialization to the database uses standard Jackson: new ObjectMapper().writer().writeValueAsString(o) (where o is the Map<String,Object> from my controller). - user1884155
Using backslashes will cause you all sorts of headaches. Why not use slashes? As long as you use Java API to access the resources you should be fine, also on a windows system. - Ralf
@Ralf Well, I didn't want to enforce Java's quirkyness to the clients of this API but obviously a working application is more important so I'll look into validating that the location value doesn't contain backslashes so I can warn the client that they should use forward slashes. - user1884155
@user1884155, I guess what's quirky depends on the point of view... Windows is the only OS (I am aware of) to use backslashes to separate path elements. - Ralf