簡體   English   中英

如何使用Jackson來指定某些要序列化為JSON的字段?

[英]How can I specify certain field to be serialized into JSON using Jackson?

我有Athlete和Injury兩個類,最后一個包含Athlete對象,當序列化發生時,我得到以下JSON表示形式: {"id":X,"kindOfInjury":"...","muscle":"...","side":"...","outOfTrainig":Y,"injuryDate":"2018-Jun-02","athlete":{"id":X,"firstName":"...","lastName":"...","age":X,"email":"..."}}

我不想獲取有關運動員的所有信息-只是一個id值,例如"athleteId":1 ,而不是獲取整個對象的表示形式。

因此,我發現我需要應用我的自定義序列化程序,該序列化程序在Injury類上實現StdSerializer。 所以這就是我到目前為止所得到的:

class InjurySerializer extends StdSerializer<Injury> {

    public InjurySerializer() {
        this(null);
    }

    public InjurySerializer(Class<Injury> i) {
        super(i);
    }

    @Override
    public void serialize(
            Injury value, JsonGenerator jgen, SerializerProvider provider)
            throws IOException, JsonProcessingException {

        jgen.writeStartObject();
        jgen.writeNumberField("id", value.getId());
        jgen.writeStringField("kindOfInjury", value.getKindOfInjury());
        jgen.writeStringField("muscle", value.getMuscle());
        jgen.writeStringField("side", value.getSide());
        jgen.writeNumberField("outOfTraining", value.getOutOfTraining());
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MMM-dd");
        Date date = new Date();
        String ourformat = formatter.format(date.getTime());
        jgen.writeStringField("injuryDate", ourformat);
        jgen.writeNumberField("athleteId", value.getAthlete().getId());
        jgen.writeEndObject();
    }
}

以及實際的傷害類別:

@Entity
@Table(name = "INJURY")
@JsonSerialize(using = InjurySerializer.class)
public class Injury {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "INJURY_ID")
    private Long id;

    @Column(name = "KIND_OF_INJURY")
    private String kindOfInjury;

    @Column(name = "MUSCLE")
    private String muscle;

    @Column(name = "SIDE")
    private String side;

    @Column(name = "OUT_OF_TRAINING")
    private Integer outOfTraining;

    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MMM-dd")
    @Column(name = "INJURY_DATE")
    private Date injuryDate;

    @ManyToOne
    @JoinColumn(name = "ATHLETE_ID")
    private Athlete athlete;

因此,此解決方案有效,但看起來很糟糕...

問題如下: 1)是否有任何機制可以為我提供僅更改我真正需要的一個屬性的序列化功能,而不是編寫所有僅此行的繁瑣代碼,而無需編寫所有繁瑣的代碼?

jgen.writeNumberField("athleteId", value.getAthlete().getId());

2)您能推薦我一些有關傑克遜的文章,因為在這一點上我對此有些困惑嗎?

感謝您的耐心配合,我們期待您的答復:)

您可能會發現使用@JsonIgnore批注而不是編寫自定義序列化程序會比較@JsonIgnore 舉個例子

public class Person {

  private int id;

  @JsonIgnore
  private String first;

  @JsonIgnore
  private String last;

  @JsonIgnore
  private int age;

  // getters and setters omitted
}

當Jackson序列化此類時,它僅在結果JSON中包含“ id”屬性。

  @Test
  void serialize_only_includes_id() throws JsonProcessingException {
    final var person = new Person();
    person.setId(1);
    person.setFirst("John");
    person.setLast("Smith");
    person.setAge(22);

    final var mapper = new ObjectMapper();
    final var json = mapper.writeValueAsString(person);
    assertEquals("{\"id\":1}", json);
  }

為此,可以使用數據傳輸對象(DTO)。

像這樣創建一個簡單的POJO:

public class InjuryDTO {

  //all other required fields from Injury model...

  @JsonProperty("athlete_id")
  private Long athleteId;
}

並為其轉換:

@Component
public class InjuryToDTOConverter{

  public InjuryDTO convert(Injury source){
    InjuryDTO target = new InjuryDTO();
    BeanUtils.copyProperties(source, target); //it will copy fields with the same names
    target.setAthleteId(source.getAthlete().getId());
    return target;
  }
}

您可以這樣使用它:

@RestController("/injuries")
public class InjuryController {

  @Autowired
  private InjuryToDTOConverter converter;

  @Autowired
  private InjuryService injuryService;

  @GetMapping
  public InjuryDTO getInjury(){
    Injury injury = injuryService.getInjury();
    return converter.convert(injury);
  }
}

這種方法的好處是,您可以具有多個用於不同用途的DTO。

您可以嘗試使用基本的字符串替換方法來處理json字符串。 我運行了您的json並將其轉換為所需的格式:

public static void main(String args[]) {
    String json = "{\"id\":123,\"kindOfInjury\":\"...\",\"muscle\":\"...\",\"side\":\"...\",\"outOfTrainig\":Y,\"injuryDate\":\"2018-Jun-02\",\"athlete\":{\"id\":456,\"firstName\":\"...\",\"lastName\":\"...\",\"age\":14,\"email\":\"...\"}}";
    JsonObject injury = new JsonParser().parse(json).getAsJsonObject();
    JsonObject athelete = new JsonParser().parse(injury.get("athlete").toString()).getAsJsonObject();
    String updateJson = injury.toString().replace(injury.get("athlete").toString(), athelete.get("id").toString());
    updateJson = updateJson.replace("athlete", "athleteId");
    System.out.println(updateJson);
}

輸出:

{"id":123,"kindOfInjury":"...","muscle":"...","side":"...","outOfTrainig":"Y","injuryDate":"2018-Jun-02","athleteId":456}

依賴關系:

implementation 'com.google.code.gson:gson:2.8.5'

如果可以用正則表達式替換,它將更加干凈。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM