何を言っているのか分からねーと思うが、俺も何が起きたのか分からなかった...
以下のようなEnum1をJSON Object
として変換すると・・・
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum Planet {
MERCURY(3.303e+23, 2.4397e6),
VENUS(4.869e+24, 6.0518e6),
EARTH(5.976e+24, 6.37814e6),
MARS(6.421e+23, 3.3972e6),
JUPITER(1.9e+27, 7.1492e7),
SATURN(5.688e+26, 6.0268e7),
URANUS(8.686e+25, 2.5559e7),
NEPTUNE(1.024e+26, 2.4746e7);
private final double mass; // in kilograms
private final double radius; // in meters
private Planet(double mass, double radius) {
this.mass = mass;
this.radius = radius;
}
// universal gravitational constant (m3 kg-1 s-2)
public static final double G = 6.67300E-11;
public double getMass() {
return mass;
}
public double getRadius() {
return radius;
}
@JsonProperty
public double surfaceGravity() {
return G * mass / (radius * radius);
}
}
以下のような出力になります。
{"mass":1.9E27,"radius":7.1492E7,"surfaceGravity":24.80617666947324}
デフォルトがキャメルケースなので、PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES
を指定してスネークケースで出力されるようにしてみます。
すると・・・
ObjectMapper mapper = new ObjectMapper()
.setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES)
String json = mapper.writeValueAsString(Planet.JUPITER);
System.out.println(json);
{"mass":1.9E27,"radius":7.1492E7,"surface_gravity":24.80617666947324,"declaring_class":"sample.jackson.Planet"}
このようにスネークケースにはなるのですが、declaring_class
というプロパティが出力されるようになってしまいます。
一応、BasicSerializerFactory#buildEnumSerializer(SerializationConfig, JavaType, BeanDescription)
で、拾ってきてしまったjava.lang.Enum#getDeclaringClass()
を除外しようとしているみたいなのですが・・・
/* As per [Issue#24], may want to use alternate shape, serialize as JSON Object.
* Challenge here is that EnumSerializer does not know how to produce
* POJO style serialization, so we must handle that special case separately;
* otherwise pass it to EnumSerializer.
*/
JsonFormat.Value format = beanDesc.findExpectedFormat(null);
if (format != null && format.getShape() == JsonFormat.Shape.OBJECT) {
// one special case: suppress serialization of "getDeclaringClass()"...
((BasicBeanDescription) beanDesc).removeProperty("declaringClass");
// returning null will mean that eventually BeanSerializer gets constructed
return null;
}
このようにキャメルケースでベタ書きしています。
スネークケースを指定した場合にココか動いていないようにも見えるので、非常に不安になるコードです。
/**
* Method that can be used to prune unwanted properties, during
* construction of serializers and deserializers.
* Use with utmost care, if at all...
*
* @since 2.1
*/
public boolean removeProperty(String propName)
{
Iterator<BeanPropertyDefinition> it = _properties.iterator();
while (it.hasNext()) {
BeanPropertyDefinition prop = it.next();
if (prop.getName().equals(propName)) {
it.remove();
return true;
}
}
return false;
}
・・・うーん、BeanPropertyDefinition#getName()
と比較していますが、今回の場合だと "declaringClass" ではなく "declaring_class" が設定されています。まさかとは思いましたが、結構単純なミスじゃないかと思われます。
あえて "declaringClass" を指定したということはStrategyに左右されなそうなBeanPropertyDefinition#getInternalName()
を使うべきだったのではないかと。。。
/**
* Accessor that can be used to determine implicit name from underlying
* element(s) before possible renaming. This is the "internal"
* name derived from accessor ("x" from "getX"), and is not based on
* annotations or naming strategy.
*/
public abstract String getInternalName();