У меня есть требование написать решение и библиотеку 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"
]
}
}
}
]
}
}
}
Правила следующие:
Я копался и хотел бы узнать ваши мысли о наилучшем подходе и библиотеках Node для решения этой проблемы в Javascript NodeJS.