Configure visibility (#29797)
This commit is contained in:
parent
0d6282cffe
commit
24d01a101a
4 changed files with 108 additions and 1 deletions
|
|
@ -126,6 +126,20 @@ akka.serialization.jackson {
|
||||||
# }
|
# }
|
||||||
json-write-features {}
|
json-write-features {}
|
||||||
|
|
||||||
|
# Configuration of the JsonFactory Visibility.
|
||||||
|
# See com.fasterxml.jackson.annotation.PropertyAccessor
|
||||||
|
# and com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility
|
||||||
|
# Enum values. For example, to serialize only public fields
|
||||||
|
# overwrite the default values with:
|
||||||
|
#
|
||||||
|
# visibility {
|
||||||
|
# FIELD = PUBLIC_ONLY
|
||||||
|
# }
|
||||||
|
# Default: all fields (including private and protected) are serialized.
|
||||||
|
visibility {
|
||||||
|
FIELD = ANY
|
||||||
|
}
|
||||||
|
|
||||||
# Deprecated, use `allowed-class-prefix` instead
|
# Deprecated, use `allowed-class-prefix` instead
|
||||||
whitelist-class-prefix = []
|
whitelist-class-prefix = []
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -179,6 +179,25 @@ object JacksonObjectMapperProvider extends ExtensionId[JacksonObjectMapperProvid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private def configureObjectVisibility(
|
||||||
|
bindingName: String,
|
||||||
|
objectMapper: ObjectMapper,
|
||||||
|
objectMapperFactory: JacksonObjectMapperFactory,
|
||||||
|
config: Config): Unit = {
|
||||||
|
|
||||||
|
val configuredVisibility: immutable.Seq[(PropertyAccessor, JsonAutoDetect.Visibility)] =
|
||||||
|
configPairs(config, "visibility").map {
|
||||||
|
case (property, visibility) =>
|
||||||
|
PropertyAccessor.valueOf(property) -> JsonAutoDetect.Visibility.valueOf(visibility)
|
||||||
|
}
|
||||||
|
val visibility =
|
||||||
|
objectMapperFactory.overrideConfiguredVisibility(bindingName, configuredVisibility)
|
||||||
|
visibility.foreach {
|
||||||
|
case (property, visibility) => objectMapper.setVisibility(property, visibility)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private def configureObjectMapperModules(
|
private def configureObjectMapperModules(
|
||||||
bindingName: String,
|
bindingName: String,
|
||||||
objectMapper: ObjectMapper,
|
objectMapper: ObjectMapper,
|
||||||
|
|
@ -244,8 +263,9 @@ object JacksonObjectMapperProvider extends ExtensionId[JacksonObjectMapperProvid
|
||||||
|
|
||||||
configureObjectMapperFeatures(bindingName, mapper, objectMapperFactory, config)
|
configureObjectMapperFeatures(bindingName, mapper, objectMapperFactory, config)
|
||||||
configureObjectMapperModules(bindingName, mapper, objectMapperFactory, config, dynamicAccess, log)
|
configureObjectMapperModules(bindingName, mapper, objectMapperFactory, config, dynamicAccess, log)
|
||||||
|
configureObjectVisibility(bindingName, mapper, objectMapperFactory, config)
|
||||||
|
|
||||||
mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)
|
mapper
|
||||||
}
|
}
|
||||||
|
|
||||||
private def isModuleEnabled(fqcn: String, dynamicAccess: DynamicAccess): Boolean =
|
private def isModuleEnabled(fqcn: String, dynamicAccess: DynamicAccess): Boolean =
|
||||||
|
|
@ -264,6 +284,12 @@ object JacksonObjectMapperProvider extends ExtensionId[JacksonObjectMapperProvid
|
||||||
val cfg = config.getConfig(section)
|
val cfg = config.getConfig(section)
|
||||||
cfg.root.keySet().asScala.map(key => key -> cfg.getBoolean(key)).toList
|
cfg.root.keySet().asScala.map(key => key -> cfg.getBoolean(key)).toList
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private def configPairs(config: Config, section: String): immutable.Seq[(String, String)] = {
|
||||||
|
import akka.util.ccompat.JavaConverters._
|
||||||
|
val cfg = config.getConfig(section)
|
||||||
|
cfg.root.keySet().asScala.map(key => key -> cfg.getString(key)).toList
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -534,4 +560,20 @@ class JacksonObjectMapperFactory {
|
||||||
@unused bindingName: String,
|
@unused bindingName: String,
|
||||||
configuredFeatures: immutable.Seq[(JsonWriteFeature, Boolean)]): immutable.Seq[(JsonWriteFeature, Boolean)] =
|
configuredFeatures: immutable.Seq[(JsonWriteFeature, Boolean)]): immutable.Seq[(JsonWriteFeature, Boolean)] =
|
||||||
configuredFeatures
|
configuredFeatures
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visibility settings used to configure the `JsonFactoryBuilder` that, if provided, will later be used to create
|
||||||
|
* an `ObjectMapper`. These settings can be amended programmatically by overriding this method and return the values
|
||||||
|
* that are to be applied to the `JsonFactoryBuilder`.
|
||||||
|
*
|
||||||
|
* @param bindingName bindingName name of this `ObjectMapper`
|
||||||
|
* @param configuredFeatures the list of `PropertyAccessor`/`JsonAutoDetect.Visibility` that were configured in
|
||||||
|
* `akka.serialization.jackson.visibility`
|
||||||
|
*/
|
||||||
|
def overrideConfiguredVisibility(
|
||||||
|
@unused bindingName: String,
|
||||||
|
configuredFeatures: immutable.Seq[(PropertyAccessor, JsonAutoDetect.Visibility)])
|
||||||
|
: immutable.Seq[(PropertyAccessor, JsonAutoDetect.Visibility)] =
|
||||||
|
configuredFeatures
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -528,4 +528,15 @@ public interface JavaTestMessages {
|
||||||
return name != null ? name.hashCode() : 0;
|
return name != null ? name.hashCode() : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A class with non-public fields
|
||||||
|
final class ClassWithVisibility {
|
||||||
|
public final String publicField = "1234";
|
||||||
|
final String defaultField = "abcd";
|
||||||
|
protected final String protectedField = "vwxyz";
|
||||||
|
private final String privateField = "ABCD";
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public ClassWithVisibility() {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -411,6 +411,46 @@ class JacksonJsonSerializerSpec extends JacksonSerializerSpec("jackson-json") {
|
||||||
"be possible to create custom ObjectMapper" in {
|
"be possible to create custom ObjectMapper" in {
|
||||||
pending
|
pending
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"be possible to tune the visibility at ObjectMapper level (FIELD, PUBLIC_ONLY)" in {
|
||||||
|
withSystem("""
|
||||||
|
akka.actor {
|
||||||
|
serialization-bindings {
|
||||||
|
"akka.serialization.jackson.JavaTestMessages$ClassWithVisibility" = jackson-json
|
||||||
|
}
|
||||||
|
}
|
||||||
|
akka.serialization.jackson.visibility {
|
||||||
|
FIELD = PUBLIC_ONLY
|
||||||
|
}
|
||||||
|
""") { sys =>
|
||||||
|
val msg = new ClassWithVisibility();
|
||||||
|
val json = serializeToJsonString(msg, sys)
|
||||||
|
val expected = """{"publicField":"1234"}"""
|
||||||
|
json should ===(expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test ensures the default behavior in Akka 2.6 series
|
||||||
|
// (that is "FIELD = ANY") stays consistent
|
||||||
|
"be possible to tune the visibility at ObjectMapper level (Akka default)" in {
|
||||||
|
withSystem("""
|
||||||
|
akka.actor {
|
||||||
|
serialization-bindings {
|
||||||
|
"akka.serialization.jackson.JavaTestMessages$ClassWithVisibility" = jackson-json
|
||||||
|
}
|
||||||
|
}
|
||||||
|
akka.serialization.jackson.visibility {
|
||||||
|
## No overrides
|
||||||
|
}
|
||||||
|
""") { sys =>
|
||||||
|
val msg = new ClassWithVisibility();
|
||||||
|
val json = serializeToJsonString(msg, sys)
|
||||||
|
val expected =
|
||||||
|
"""{"publicField":"1234","defaultField":"abcd","protectedField":"vwxyz","privateField":"ABCD"}""".stripMargin
|
||||||
|
json should ===(expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"JacksonJsonSerializer with Scala message classes" must {
|
"JacksonJsonSerializer with Scala message classes" must {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue