繁体   English   中英

获取同一对象的不同JSON表示

[英]Get different JSON representations of the same object

给定一个与Jackson一起序列化为JSON字符串的java对象。 是否可以控制序列化过程从同一对象生成不同的JSON输出?

压缩:

{
  "a":"123",
  "s":"100"
}

或正常:

{
  "altitude":"123",
  "speed":"100"
}

编辑:我想要实现的目标是拥有一个长JSON格式,这对于调试(人类可读)很好,并且具有提供最小占用空间的压缩格式。

你可以通过很多方式做到这一点。 这取决于您的要求。 我建议你实现自己的属性命名策略。 见下面的例子:

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}

看看谷歌的Gson图书馆。 它非常快速和灵活,并且可以在表示中排除(请参阅@Foo )或重命名字段(请参阅@SerializedName("...") )。

只是一个提案...... :)

ps :如果你想使用多个表示,请使用Michael提出的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);
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM