Java class JSON 的实现使用 Jackson 序列化

Java class implementation for JSON serialized using Jackson

我正在尝试在 Java 应用程序中实现 Microsoft Teams API 的一部分,我正在寻找一些关于正确 Java class 使用 Jackson 库将 Java 对象序列化为 JSON 时的结构和体系结构。目标是在某些阶段完成时向 Teams 频道发送消息。

我有一个测试 class 可以精确地序列化 JSON 我想要的,但是根据我见过的其他实现,下面的代码感觉它的结构不正确且不灵活。

我希望得到的 JSON 结构如下:

{
  "@context": "http://schema.org/extensions",
  "@type": "MessageCard",
  "correlationId": "104443c6-7acc-11ea-bc55-0242ac130003",
  "summary": "test.complete",
  "themeColor": "0076D7",
  "sections": [
    {
      "activityTitle": "Test Notification"
    },
    {
      "title": "Execution Status",
      "facts": [
        {
          "name": "Build Number",
          "value": "1"
        },
        {
          "name": "Description",
          "value": "Test Pipeline Description"
        },
        {
          "name": "Execution Name",
          "value": "Test Pipeline Name"
        },
        {
          "name": "Stage Name",
          "Value": "Deploy"
        },
        {
          "name": "Status",
          "value": "complete"
        },
        {
          "name": "Summary",
          "value": "pipeline has completed successfully"
        }
      ]
    }
  ],
  "potentialAction": [
    {
      "@context": "http://schema.org",
      "@type": "ViewAction",
      "name": "View Execution",
      "target": [
        "https://testdomain.com"
      ]
    }
  ]
}

我的测试Java class如下:

import java.util.*;
import com.fasterxml.jackson.annotation.*;

public class JacksonSerializerTest {
  private static String ACTIVITY_TITLE = "Test Notifications";
  private static String FACTS_TITLE = "Execution Status";

  @JsonProperty("@context")
  public String context = "http://schema.org/extensions";

  @JsonProperty("@type")
  public String type = "MessageCard";

  public String correlationId;
  public String summary;
  public String themeColor;

  private transient HashMap<String, Object> metadata;

  public JacksonSerializerTest(HashMap<String, Object> metadata) {
    this.correlationId = this.createRandomUUID();
    this.summary = "test.complete";
    this.themeColor = "0076D7";

    this.metadata = metadata;
  }

  public List<HashMap> getSections() {
    List<HashMap> sections = new ArrayList<>();
    HashMap<String, Object> activityTitle = this.getSection("activityTitle", ACTIVITY_TITLE);

    sections.add(activityTitle);
    sections.add((HashMap)this.getFacts());

    return sections;
  }

  public HashMap<String, Object> getSection(String name, Object obj) {
    HashMap<String, Object> section = new HashMap<>();

    section.put(name, obj);

    return section;
  }

  private HashMap<String, Object> getFacts() {
    HashMap<String, Object> facts = new HashMap<>();
    List<HashMap> factsList = new ArrayList<>();

    factsList.add((HashMap)this.getFact("Build Number", (String)metadata.get("buildNumber")));
    factsList.add((HashMap)this.getFact("Description", (String)metadata.get("description")));
    factsList.add((HashMap)this.getFact("Execution Name", (String)metadata.get("executionName")));
    factsList.add((HashMap)this.getFact("Stage Name", (String)metadata.get("eventName")));
    factsList.add((HashMap)this.getFact("Status", (String)metadata.get("executionStatus")));
    factsList.add((HashMap)this.getFact("Summary", (String)metadata.get("executionSummary")));

    facts.put("title", FACTS_TITLE);
    facts.put("facts", factsList);

    return facts;
  }

  public HashMap<String, String> getFact(String name, String value) {
    HashMap<String, String> fact = new HashMap<>();

    fact.put("name", name);
    fact.put("value", value);

    return fact;
  }

  public List<HashMap> getPotentialAction() {
    List<HashMap> potentialAction = new ArrayList<>();
    HashMap<String, Object> action = new HashMap<>();
    ArrayList<String> targets = new ArrayList<>();

    targets.add((String)metadata.get("executionUrl"));

    action.put("@context", "http://schema.org");
    action.put("@type", "ViewAction");
    action.put("name", "View Execution");
    action.put("target", targets);

    potentialAction.add(action);

    return potentialAction;
  }

  private static String createRandomUUID() {
    return UUID.randomUUID().toString();
  }
}

根据我一直在阅读的内容,看起来我应该对部分和 potentialAction 元素使用嵌套 classes,但我一直在努力解决如何实现嵌套 classes 输出一个数组,其中包含这些数组中的不同哈希值。

截至目前,我并不打算实现整个 API,而是希望获得特定的留言卡结构,如上面 JSON 中所示。不过,我们可能希望在以后添加其他功能或使用不同的消息类型。

如果我们确实需要添加基于 Teams API 的额外元素,如何改进此 class 以及应如何构建此 Java 对象以使其更灵活?

您可以先为 PotentialAction 和 Sections 创建单独的 classes。这是为了确保关注点分离。像 :

class PotentialAction { 
  private List<HashMap> potentialAction;
  //all business logic to generate Potential Action goes in this class
}

class Sections {
 private List<HashMap> sections;
 //all business logic to generate Sections goes in this class
}

然后你创建一个抽象 class 具有每个 api 具有的最低要求(如元数据)

abstract class APICommon {
 //compulsory attributes required by all api's
 private String accessToken;
}

现在定义 API 特定的 classes 以扩展该抽象 class

class API1 extends APICommon {
 // all the api specific attributes
  public String correlationId;
  public String summary;
  public String themeColor;
  private PotentialAction potentialAction;
  private Sections sections;
}

优点:

  1. 通过将潜在的操作和部分分成不同的 classes,使 JSON 的不同部分的业务逻辑现在分开了,这不仅使代码干净,但也可重复用于不同的 api。

  2. 继续前进,如果您有其他要求并且需要支持新的 api,您需要做的就是从我们的摘要 [=37= 中扩展另一个 class ] API常见。这确保了早期的实现不受影响,并使您的设计可扩展。

希望这对您有所帮助:)