Con la biblioteca Jackson json, es posible deserializar el objeto mediante el uso del @JsonCreator
, y se le dará el mapa de "nivel superior" que representa la entrada json, como sigue:Utilice @JacksonInject con @JsonCreator en un mapa de nivel superior
class MyClass {
final int field;
@JsonCreator
public MyClass(Map<String, Object> map) {
this.field = (int) map.get("theInt");
}
}
o incluso en un método de fábrica estática:
class MyClass {
final int field;
public MyClass(int theInt) {
this.field = theInt;
}
@JsonCreator
static MyClass create(Map<String, Object> map) {
return new MyClass((int) map.get("theInt"));
}
}
los ejemplos anteriores pueden procesar los siguientes tipos de entrada de JSON:
{
"key1":"value1",
"key2":"value2",
"key3":"value3"
}
Esto es particularmente útil en mi caso porque me gustaría deserializar una estructura json que no sé. Tener acceso a lo que llamo el "mapa de nivel superior" hace las cosas simples.
Me gustaría deserializar mis objetos de esta manera, ya que también permite crear objetos inmutables, en lugar de usar @JsonAnySetter
que no lo permite, y @JsonProperty
que no puedo usar ya que no conozco el nombre de las propiedades de antemano como he mencionado anteriormente.
Luego de ir más lejos, me gustaría inyectar un poco de configuración en mi método de fábrica, y Jackson permite esto a través del uso de @JacksonInject
y una llamada a withInjectableValues(InjectableValues)
en el ObjectMapper
.
Esto es, finalmente, el tipo de código me gustaría usar:
class MyClass {
final MyField[] myFields;
public MyClass(MyField... myFields) {
this.myFields = myFields;
}
@JsonCreator
static MyClass create(@JacksonInject("conf") Conf conf, Map<String, Object> map) {
MyFields[] myFields;
// initialize myFields (or any other object) based on the content of map
// and also make use of the inject conf
return new MyClass(myFields);
}
}
Desafortunadamente, Jackson lanza el siguiente tipo de excepciones:
- al intentar el truco en el constructor
JsonMappingException: Argument #1 of constructor [constructor for MyClass, annotations: {[email protected]()}] has no property name annotation; must have name when multiple-paramater constructor annotated as Creator
- al intentar el truco en el método de fábrica
JsonMappingException: Argument #1 of factory method [method create, annotations: {[email protected]()}] has no property name annotation; must have when multiple-paramater static method annotated as Creator
¿Alguien sabe cómo podría resolver el problema?
Para resumir los requisitos, necesito:
- acceso al mapa de nivel superior (no sé los nombres de las propiedades JSON de antelación)
- para crear un objeto inmutable (lo que no puede utilice
@JsonAnySetter
) - para inyectar algo de conf para el método
@JsonCreator
constructor o fábrica decorada
que no puedo cambiar el formato de entrada JSON, que se ve así:
{
"key1":"value1",
"key2":"value2",
"key3":"value3"
}
[EDIT]
Este es un problema conocido: http://jira.codehaus.org/browse/JACKSON-711 (no fijado aún)
De hecho, acaba de descubrir este boleto: http://jira.codehaus.org/browse/JACKSON-711 – killy971
Ah sí. Asegúrese de votar, como dije, debería funcionar, pero lamentablemente es una de las combinaciones más complicadas de apoyar, solo por los aspectos de la implementación. – StaxMan