首页 > 解决方案 > 根据输出 JSON 模式从输入 JSON 消息生成输出 JSON 消息

问题描述

我需要编写一个 NodeJS 解决方案和库来接收输入 JSON 数据,该解决方案必须将其转换为与提供的输出 JSON 模式匹配或验证的输出 JSON 数据。

目前,我有一个输入文件,它验证目标 JSON 模式,但缺少一些字段和默认值,业务规则允许作为转换的一部分。

源 JSON 如下:

    {
    "messageContext" : {
        "statement" : "mediaDelivered",
        "services" :[
            "mss"
        ],
        "domain":"my.xxx.yyy.create",
        "function":"FCG"

    },
    "header" : {
        "primaryEntityIDs":[
            "my:png::abcxxxx"
        ],
        "origin" : "my-png",

    },
    "data" :{
        "operation": "CREATE",
        "payload": {
            "s3": "https://wildwildwest.amazonaws.com/png/myimg.mov"
        }

    }
}

生成的输出 JSON 必须匹配或验证到的 JSON 模式如下:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://schema.example.com/v1-0-0/schema.json",
  "definitions": {
    "header": {
      "type": "object",
      "title": "Message headers",
      "description": "Header properties for the message.",
      "required": [
        "serializedVersion",
        "correlationID",
        "projectID",
        "sourceMessageID",
        "eventTimestamp",
        "messageType",
        "primaryEntityIDs"
      ],
      "additionalProperties": false,
      "properties": {
        "serializedVersion": {
          "type": "string",
          "title": "serialized Version",
          "description": "The version of the schema to validate this message against, the SchemaVer convention.",
          "default": "1-0-0",
          "pattern": "^([1-9][0-9]*)-(0|[1-9][0-9]*)-(0|[1-9][0-9]*)$",
          "examples": [
            "1-0-0"
          ]
        },
        "correlationID": {
          "type": "string",
          "title": "Correlation ID",
          "description": "Use this field to pass on the ID from an upstream message. If you do not have an upstream message, please create a guid.",
          "examples": [
            "4fd5217e-a3d8-4ffc-8b8c-76ea9ba0ccdb"
          ]
        },
        "projectID": {
          "type": "string",
          "title": "Project ID",
          "description": "An ID for the current project, which is a grouping of messages that apply to a specific business context. For example: a commission, creating a new content version, migrating programmes to a new brand.",
          "examples": [
            "4fd5217e-a3d8-4ffc-8b8c-76ea9ba0ccdb"
          ]
        },
        "sourceMessageID": {
          "type": "string",
          "title": "Source Message ID",
          "description": "A unique ID for this message. Generated by the system that generates the message.",
          "examples": [
            "6b659d8f-bf4b-4dbe-8d31-5c6e9b8553b6"
          ]
        },
        "eventTimestamp": {
          "type": "string",
          "title": "Event Timestamp",
          "description": "The ISO 8601 datetime at which this message was created. Generated by the system that generates the message.",
          "examples": [
            "2015-07-09T10:45:01.555Z"
          ],
          "format": "date-time"
        },
        "expiryTime": {
          "type": "string",
          "title": "Expiry Time",
          "description": "The ISO 8601 datetime at which the message is no longer applicable. For a status message this would mean that the status message should be ignored after this time and the information in it considered no longer true. Timezone must be provided. Accuracy greater than 1s is not supported, greater accuracy will be truncated. If not provided time for hh, mm, or ss defaults to 00.",
          "examples":[
            "2015-07-09T10:45:01.555Z"
          ],
          "format": "date-time"
        },
        "origin": {
          "type": "string",
          "title": "origin",
          "description": "The specific system that generated this message. This field is for information only, and should not be coupled to. To understand the source of a message, please use messageContext/Function. This allows for looser coupling between systems and for multiple systems to provide the same function.",
          "examples": [
            "media-selector"
          ]
        },
        "messageType": {
          "type": "string",
          "title": "Message Type",
          "description": "The type of serialized message.",
          "enum": [
            "STATUS",
            "COMMAND",
            "ERROR"
          ],
          "examples": [
            "STATUS"
          ]
        },
        "inResponseTo": {
          "type": "string",
          "title": "In Response To",
          "description": "The message ID that this message is in response to.",
          "examples": [
            "6b659d8f-bf4b-4dbe-8d31-5c6e9b8553b6"
          ]
        },
        "primaryEntityIDs": {
          "type": "array",
          "title": "Primary Entity IDs",
          "description": "A list of equivalent IDs (preferably URIs) that systems use to describe the content this message is about. For example, this may contain a What's On UID, and a PEEPS version ID. Any further entity identifiers can be in the Payload section (for example the identifier of an availability document).",
          "items": {
            "type": "string",
            "title": "ID",
            "description": "IDs (preferably URIs) for my content identifiers.",
            "examples": [
              "urn:my:CMM1:uid:ABC123E/01",
              "urn:my:DST1:pid:p00123"
            ]
          }
        }
      }
    },
    "messageContext": {
      "type": "object",
      "title": "Message Context",
      "description": "The message context, combined with the Content-IDs section should contain all of the information needed to understand the purpose of this message.",
      "required": [
        "domain",
        "function",
        "statement"
      ],
      "additionalProperties": false,
      "properties": {
        "services": {
          "type": "array",
          "title": "Services",
          "description": "A list of services that this message is relevant to. For example, the editorial description of a piece of content may be approved only for on-platform services, such as mediaplayer.",
          "items": {
            "type": "string",
            "title": "A my service",
            "examples": [
              "mediaplayer",
              "my-plus",
              "twitter"
            ]
          }
        },
        "domain": {
          "type": "string",
          "title": "Domain",
          "description": "The top level address of the function sending the message. This follows a dot notation, starting with the company (e.g. my), moving down a domain hierarchy.",
          "examples": [
            "my.content.distribution"
          ]
        },
        "function": {
          "type": "string",
          "title": "Function",
          "description": "The business function sending the message. This is the generic function that the sending system is providing when sending this message. For example, Media Selector is providing the function of AvailabilityManagement, within the distribution domain. One system may have grown to provide more than one function, in which case the specific function that applies to this message should be used.",
          "examples": [
            "availabilityManagement"
          ]
        },
        "contentTypes": {
          "type": "array",
          "title": "Content Types",
          "description": "The content type that this message applies to. In the AvailabilityManagement example, this could separately message the availability of media, or document data separately, or together.",
          "items": {
            "type": "string",
            "enum": [
              "MEDIA",
              "DOCUMENT"
            ],
            "examples": [
              "MEDIA"
            ]
          }
        },
        "statement": {
            "type": "string",
            "title": "Statement",
            "description": "The string statement being made by the message which describes the event. This must be past-tense.",
            "pattern": "(^\\S+$)",
            "examples": [
                "receivedMedia",
                "linkedToPlanningItem",
                "renditionCreated"
            ]
        }
      }
    },
    "data": {
      "type": "object",
      "title": "Data",
      "description": "Dictionary describing the type of data being transferred and the transfer method. Includes either a reference to a data entity or an entity itself in a JSON document.",
      "additionalProperties": false,
      "properties": {
        "operation": {
          "type": "string",
          "title": "Operation",
          "description": "The CRUD operation that was performed.",
          "enum": [
            "CREATE",
            "READ",
            "UPDATE",
            "DELETE"
          ]
        },
        "entitySchema": {
          "type": "string",
          "title": "Entity Schema",
          "description": "The schema used for the object in the Payload.",
          "examples": [
            "http://url.my.dev/package.schema.json"
          ]
        },
        "entityType": {
          "type": "string",
          "title": "Entity Type",
          "description": "The type of entity being provided in the Payload.",
          "examples": [
            "package"
          ]
        }
      },
      "anyOf": [
        {
          "required": [
            "payload"
          ],
          "properties": {
            "payload": {
              "type": "object",
              "title": "Payload",
              "description": "The data entity being transferred. If both a reference and a payload are provided, then the objects in both must be identical.",
              "properties": {},
              "additionalProperties": true
            }
          }
        },
        {
          "required": [
            "reference"
          ],
          "properties": {
            "reference": {
              "type": "string",
              "title": "Reference",
              "description": "A reference to the data entity being transferred. If both a reference and a payload are provided, then the objects in both must be identical.",
              "examples": [
                "https://url.my.dev/3b0f45d6-9051-4939-974f-8cbb7774b1db"
              ]
            }
          }
        }
      ]
    }
  }
}

规则如下:

在此处输入图像描述

我一直在研究并想知道您对在 NodeJS Javascript 中解决此问题的最佳方法和 Node 库的想法。

标签: javascriptnode.jsjsonjavascript-objectsjsonschema

解决方案


我发现 Joi 库非常适合我的用例。我已经测试并使用了它,它对我有用,并且给了我需要控制来强制执行模式的约束。

https://www.npmjs.com/package/joi

另一个可能有用的库是https://www.npmjs.com/package/is-my-json-valid。但是,我还没有深入测试过这个库。


推荐阅读