给定一个与Jackson一起序列化为JSON字符串的java对象。 是否可以控制序列化过程从同一对象生成不同的JSON输出?
压缩:
{
"a":"123",
"s":"100"
}
或正常:
{
"altitude":"123",
"speed":"100"
}
编辑: 我想要实现的目标是拥有一个长JSON格式,这种格式适合调试(人类可读),并且具有压缩格式,可提供最小的占用空间。
答案 0 :(得分:10)
你可以通过多种方式实现这一目标。这取决于您的要求。我建议你实现自己的属性命名策略。见下面的例子:
class CompressedPropertyNamingStrategy extends PropertyNamingStrategyBase {
private static final long serialVersionUID = 1L;
@Override
public String translate(String name) {
return String.valueOf(name.charAt(0));
}
}
您可以这样使用它:
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(new CompressedPropertyNamingStrategy());
String json = mapper.writeValueAsString(new Pojo());
如果您不想压缩属性名称,只需删除第2行。
编辑1
在@aumand评论之后我想通知,这个解决方案不适用于包含许多从同一个字母开头的属性的实体。我们必须编写更复杂的解决方案。例如:
class CompressedPropertyNamingStrategy extends PropertyNamingStrategyBase {
private static final long serialVersionUID = 1L;
private final int length;
public CompressedPropertyNamingStrategy(int length) {
this.length = length;
}
@Override
public String translate(String name) {
if (name.length() < length) {
return name;
}
return name.substring(0, length);
}
}
编辑2
如果您确实希望在序列化过程中控制属性名称,则应实现自己的注释。例如:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(value = { ElementType.METHOD, ElementType.FIELD })
@Retention(value = RetentionPolicy.RUNTIME)
public @interface CompressedName {
String value();
}
在这种情况下,您的命名策略可能如下所示:
class CompressedPropertyNamingStrategy extends PropertyNamingStrategy {
private static final long serialVersionUID = 1L;
@Override
public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method,
String defaultName) {
CompressedName compressedProperty = method.getAnnotation(CompressedName.class);
if (compressedProperty != null) {
return compressedProperty.value();
}
// Implement default value: first letter, or something else
return defaultName;
}
}
现在,您必须为实体方法添加注释:
class Entity {
private long altitude = 123;
private int speed = 100;
@CompressedName("a")
public long getAltitude() {
return altitude;
}
public void setAltitude(long altitude) {
this.altitude = altitude;
}
@CompressedName("sp")
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
}
在此方案示例中,JSON可能如下所示:
{"a":123,"sp":100}
答案 1 :(得分:2)
查看Google的Gson库。它非常快速灵活,可以在表示中排除(参见@Foo
)或重命名字段(请参阅@SerializedName("...")
)。
只是提案......:)
p.s。:如果您想使用多个表示,请使用迈克尔提出的FieldNamingStrategy
,例如:
GsonBuilder gsonBuilder = new GsonBuilder();
if (format == "compressed")
gsonBuilder.setFieldNamingStrategy(new CompressedFieldNamingStrategy());
Gson gson = gsonBuilder.create();
...
class CompressedFieldNamingStrategy implements FieldNamingStrategy
{
private static HashTable translations = new HashMap<String, String>() {
{ put("altitude", "a"); put("speed", "s"); ...}
};
@Override
public String translateName(Field field)
{
String name = field.getName();
return translation.get(name);
}
}