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

标签 java json serialization jackson microsoft-teams

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

我有一个测试类,它序列化为我想要的确切 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 类如下:

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();
  }
}

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

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

如果我们确实需要基于 Teams API 添加其他元素,如何改进此类以及如何构造该 Java 对象以使其更加灵活?

最佳答案

您可以首先为 PotentialAction 和部分创建单独的类。这是为了确保关注点分离。像这样的东西:

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
}

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

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

现在定义 API 特定类来扩展该抽象类

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. 通过将潜在的操作和部分分离到不同的类中,用于制作 JSON 不同部分的业务逻辑现在被分离,这不仅使代码变得干净,而且可以为不同的 api 重用。

    <
  2. 如果您有其他要求并且需要支持新的 api,您所需要做的就是从我们的抽象类 APICommon 扩展另一个类。这可以确保早期的实现不受影响并使您的设计具有可扩展性。

希望这有帮助:)

关于使用 Jackson 序列化 JSON 的 Java 类实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61254483/

相关文章:

java - 转换/导出到 libgdx G3D

java - 我必须重构我的代码,但不知道将碰撞方法放在哪里

java - 在网络应用程序中上传图像

ruby-on-rails - 如何在 Rails 或 Ruby 中使用 json 或 xml 网络服务?

python - 类型错误 : Object of type 'datetime' is not JSON serializable (with serialize function)

java - 尝试 catch block 变量超出范围

java - jackson 反序列化具有多个名称的枚举

ios - 使用 AFNetworking 从 Open Weather Map API 解析 JSON 天气对象

c# - 反序列化包含原始类型和一种类类型的对象 []

java - yaml vs xml 用于对象图反序列化的优缺点是什么?