MX-JSON Conversion
Back and forth conversion between MX messages and JSON
Different structures are created depending on the model object where the toJson/fromJson is invoked.
AbstractMX
For the AbstractMX
model hierarchy, the JSON structure mirrors the XML message structure. The elements preserve the
same indentation and the tags are represented as keys in the JSON structure. Thus, the actual JSON structure varies
from on message type to another.
The example below contains an XML fragment of a pacs.008.001.10 and the corresponding JSON representation, for both
the Document
and the AppHdr
tags.
XML
<?xml version="1.0" encoding="UTF-8" ?>
<RequestPayload>
<h:AppHdr xmlns:h="urn:iso:std:iso:20022:tech:xsd:head.001.001.02">
<h:Fr>
<h:FIId>
<h:FinInstnId>
<h:BICFI>AAAAUS33XXX</h:BICFI>
</h:FinInstnId>
</h:FIId>
</h:Fr>
<h:To>
<h:FIId>
<h:FinInstnId>
<h:BICFI>BBBBHKHHPBB</h:BICFI>
</h:FinInstnId>
</h:FIId>
</h:To>
<h:BizMsgIdr>REF1234567</h:BizMsgIdr>
<h:MsgDefIdr>pacs.008.001.10</h:MsgDefIdr>
<h:CreDt>2023-02-03T10:35:45-05:00</h:CreDt>
<h:PssblDplct>false</h:PssblDplct>
<h:Prty>NORM</h:Prty>
</h:AppHdr>
<Doc:Document xmlns:Doc="urn:iso:std:iso:20022:tech:xsd:pacs.008.001.10">
<Doc:FIToFICstmrCdtTrf>
<Doc:GrpHdr>
<Doc:MsgId>0508420020FC</Doc:MsgId>
<Doc:CreDtTm>2023-02-03T10:35:45-05:00</Doc:CreDtTm>
<Doc:BtchBookg>false</Doc:BtchBookg>
<Doc:NbOfTxs>1</Doc:NbOfTxs>
<Doc:SttlmInf>
<Doc:SttlmMtd>INDA</Doc:SttlmMtd>
</Doc:SttlmInf>
<Doc:InstgAgt>
<Doc:FinInstnId>
<Doc:BICFI>AAAAUS33XXX</Doc:BICFI>
</Doc:FinInstnId>
</Doc:InstgAgt>
<Doc:InstdAgt>
<Doc:FinInstnId>
<Doc:BICFI>BBBBHKHHPBB</Doc:BICFI>
</Doc:FinInstnId>
</Doc:InstdAgt>
</Doc:GrpHdr>
<Doc:CdtTrfTxInf>
<Doc:PmtId>
<Doc:InstrId>REF1234567</Doc:InstrId>
<Doc:EndToEndId>REF1234567</Doc:EndToEndId>
<Doc:TxId>REF1234567</Doc:TxId>
<Doc:UETR>30ae21a8-9082-41cc-93ce-c71916241234</Doc:UETR>
</Doc:PmtId>
<Doc:IntrBkSttlmAmt Ccy="USD">400000.0</Doc:IntrBkSttlmAmt>
<Doc:IntrBkSttlmDt>2023-01-20</Doc:IntrBkSttlmDt>
<Doc:InstdAmt Ccy="USD">400000.0</Doc:InstdAmt>
<Doc:ChrgBr>SHAR</Doc:ChrgBr>
...
JSON
{
"fiToFICstmrCdtTrf": {
"grpHdr": {
"msgId": "0508420020FC",
"creDtTm": {
"dateTime": {
"date": {
"year": 2023,
"month": 2,
"day": 3
},
"time": {
"hour": 10,
"minute": 35,
"second": 45,
"nano": 0
}
},
"offset": {
"totalSeconds": -18000
}
},
"btchBookg": false,
"nbOfTxs": "1",
"sttlmInf": {
"sttlmMtd": "INDA"
},
"instgAgt": {
"finInstnId": {
"bicfi": "AAAAUS33XXX"
}
},
"instdAgt": {
"finInstnId": {
"bicfi": "BBBBHKHHPBB"
}
}
},
"cdtTrfTxInf": [
{
"pmtId": {
"instrId": "REF1234567",
"endToEndId": "REF1234567",
"txId": "REF1234567",
"uetr": "30ae21a8-9082-41cc-93ce-c719162444d5"
},
"intrBkSttlmAmt": {
"value": 400000.0,
"ccy": "USD"
},
"intrBkSttlmDt": {
"year": 2023,
"month": 1,
"day": 20
},
"instdAmt": {
"value": 400000.0,
"ccy": "USD"
},
"chrgBr": "SHAR",
...
]
},
"appHdr": {
"fr": {
"fiId": {
"finInstnId": {
"bicfi": "AAAAUS33XXX"
}
}
},
"to": {
"fiId": {
"finInstnId": {
"bicfi": "BBBBHKHHPBB"
}
}
},
"bizMsgIdr": "REF1234567",
"msgDefIdr": "pacs.008.001.10",
"creDt": {
"dateTime": {
"date": {
"year": 2023,
"month": 2,
"day": 3
},
"time": {
"hour": 10,
"minute": 35,
"second": 45,
"nano": 0
}
},
"offset": {
"totalSeconds": -18000
}
},
"pssblDplct": false,
"prty": "NORM",
"namespace": "urn:iso:std:iso:20022:tech:xsd:head.001.001.02"
},
"type": "MX",
"@xmlns": "urn:iso:std:iso:20022:tech:xsd:pacs.008.001.10",
"identifier": "pacs.008.001.10"
}
The only elements that contains a different representation between the XML and the JSON are the ones containing dates and time information.
For example this date and time in XML:
Is represented in JSON with a more structured format:
{
"creDtTm": {
"dateTime": {
"date": {
"year": 2023,
"month": 2,
"day": 3
},
"time": {
"hour": 10,
"minute": 35,
"second": 45,
"nano": 0
}
},
"offset": {
"totalSeconds": -18000
}
}
}
Note: If you're transitioning to version 10.x.x of the library, please note that all XML elements modelled as
XmlGregorianCalendar
in previous versions have been changed to specific classes from the java.time
package.
This change aligns with Java's shift towards more modern and efficient development practices. Ensure to update your
implementations accordingly.
Date and Time formats
This sections describes the formats used for the different date and time data types in the JSON representation.
LocalDate
If the model contains an element of type LocalDate
, the JSON representation will be:
OffsetDateTime
If the model contains an element of type OffsetDateTime
, the JSON representation will be as follows.
Without offset:
{
"dateTime":{
"date":{
"year":2019,
"month":4,
"day":28
},
"time":{
"hour":12,
"minute":13,
"second":14,
"nano":0
}
}
}
Without offset nor nanoseconds:
{
"dateTime":{
"date":{
"year":2019,
"month":4,
"day":28
},
"time":{
"hour":12,
"minute":13,
"second":14
}
}
}
Without offset, seconds nor nanoseconds:
With offset, seconds and nanoseconds:
{
"dateTime":{
"date":{
"year":2019,
"month":4,
"day":28
},
"time":{
"hour":12,
"minute":13,
"second":14,
"nano":123456789
}
},
"offset":{
"totalSeconds":"-1800"
}
}
OffsetTime
If the model contains an element of type OffsetTime
, the JSON representation will be as follows.
Without offset:
Without offset nor nanoseconds:
Without offset, seconds nor nanoseconds:
With offset, seconds and nanoseconds:
Year
If the model contains an element of type Year`, the JSON representation will be:
YearMonth
If the model contains an element of type YearMonth
, the JSON representation will be:
AbstractMX to Json conversion
In case of need to serialize the message into a JSON structure, the toJson()
method should be used.
The result will vary depending on the class model extending the AbstractMX class that's being transformed.
The code in the sample below:
MxPain00100108 mx = new MxPain00100108();
mx.setCstmrCdtTrfInitn(new CustomerCreditTransferInitiationV08());
mx.getCstmrCdtTrfInitn().setGrpHdr(new GroupHeader48());
mx.getCstmrCdtTrfInitn().getGrpHdr().setCtrlSum(new BigDecimal("1234.56"));
mx.getCstmrCdtTrfInitn().getGrpHdr().setMsgId("MYID");
OffsetDateTime offsetDateTime = OffsetDateTime.now();
mx.getCstmrCdtTrfInitn().getGrpHdr().setCreDtTm(offsetDateTime);
mx.getCstmrCdtTrfInitn().getGrpHdr().setNbOfTxs("1");
mx.getCstmrCdtTrfInitn().getGrpHdr().setInitgPty(new PartyIdentification43());
mx.getCstmrCdtTrfInitn().getGrpHdr().getInitgPty().setNm("Joe Doe");
mx.getCstmrCdtTrfInitn().getGrpHdr().getInitgPty().setCtryOfRes("USA");
mx.getCstmrCdtTrfInitn().getGrpHdr().getInitgPty().setId(new Party11Choice());
mx.getCstmrCdtTrfInitn().getGrpHdr().getInitgPty().getId().setOrgId(new OrganisationIdentification8());
mx.getCstmrCdtTrfInitn().getGrpHdr().getInitgPty().getId().getOrgId().setAnyBIC("FOOBARXX");
mx.getCstmrCdtTrfInitn().getGrpHdr().setFwdgAgt(new BranchAndFinancialInstitutionIdentification5());
mx.getCstmrCdtTrfInitn().getGrpHdr().getFwdgAgt().setBrnchId(new BranchData2());
mx.getCstmrCdtTrfInitn().getGrpHdr().getFwdgAgt().getBrnchId().setId("Ident1234");
mx.getCstmrCdtTrfInitn().getGrpHdr().getFwdgAgt().getBrnchId().setNm("A Name");
String json = mx.toJson();
System.out.println(json);
Will result in the next json message:
{
'cstmrCdtTrfInitn': {
'grpHdr': {
'msgId': 'MYID',
'creDtTm': {
'dateTime': {
'date': {
'year': 2023,
'month': 9,
'day': 4
},
'time': {
'hour': 12,
'minute': 3,
'second': 57,
'nano': 593101500
}
},
'offset': {
'totalSeconds': -10800
}
},
'nbOfTxs': '1',
'ctrlSum': 1234.56,
'initgPty': {
'nm': 'Joe Doe',
'id': {
'orgId': {
'anyBIC': 'FOOBARXX'
}
},
'ctryOfRes': 'USA'
},
'fwdgAgt': {
'brnchId': {
'id': 'Ident1234',
'nm': 'A Name'
}
}
}
},
'type': 'MX',
'@xmlns': 'urn:iso:std:iso:20022:tech:xsd:pain.001.001.08',
'identifier': 'pain.001.001.08'
}
Json to AbstractMX conversion
In case of need to convert a json formatted message into a model object, the AbstractMx#fromJson(String json)
method should be used.
The conversion will result in a concrete class of the message type that's being parsed.
Please note that casting is needed in order to access the model structure.
final String json = "{"
+ " 'fiCdtTrf': {"
+ " 'grpHdr': {"
+ " 'msgId': 'A2P76703',"
+ " 'creDtTm': {"
+ " 'dateTime': {"
+ " 'date': {"
+ " 'year': 2021,"
+ " 'month': 4,"
+ " 'day': 28"
+ " },"
+ " 'time': {"
+ " 'hour': 23,"
+ " 'minute': 35,"
+ " 'second': 53,"
+ " 'nano': 123456789"
+ " }"
+ " },"
+ " 'offset': {"
+ " 'totalSeconds': -10800"
+ " }"
+ " },"
+ " 'nbOfTxs': '1'"
+ " }"
+ " },"
+ " 'appHdr': {"
+ " 'from': {"
+ " 'type': 'BIC',"
+ " 'id': 'ABNANL20606'"
+ " },"
+ " 'to': {"
+ " 'type': 'BIC',"
+ " 'id': 'GIISIT2TXXX'"
+ " },"
+ " 'msgName': 'pacs.009.001.07',"
+ " 'msgRef': 'CPTE190421113270',"
+ " 'crDate' : {"
+ " 'dateTime': {"
+ " 'date': {"
+ " 'year': 2023,"
+ " 'month': 9,"
+ " 'day': 4"
+ " },"
+ " 'time': {"
+ " 'hour': 12,"
+ " 'minute': 3,"
+ " 'second': 57,"
+ " 'nano': 593101500"
+ " }"
+ " },"
+ " 'offset': {"
+ " 'totalSeconds': -10800"
+ " }"
+ " }"
+ " },"
+ " 'type': 'MX',"
+ " '@xmlns': 'urn:iso:std:iso:20022:tech:xsd:pacs.009.001.07',"
+ " 'identifier': 'pacs.009.001.07'"
+ "}";
AbstractMX abstractMX = AbstractMX.fromJson(json);
assertEquals("pacs.009.001.07", abstractMX.getMxId().toString());
assertEquals("CPTE190421113270", abstractMX.getAppHdr().reference());
MxPacs00900107 mx = (MxPacs00900107) abstractMX;
assertEquals("A2P76703", mx.getFICdtTrf().getGrpHdr().getMsgId());
assertEquals(
"2021-04-28T23:35:53.123456789-03:00",
mx.getFICdtTrf().getGrpHdr().getCreDtTm().toString());
assertEquals("2023-09-04T12:03:57.593101500-03:00", mx.getAppHdr().creationDate().toString());
It is also possible to use the concrete model class fromJson(String json)
method in order to avoid casting
if the json message type is already known.
String source = "{"
+ " 'sctiesSttlmTxInstr': {"
+ " 'id': {"
+ " 'creDtTm': {"
+ " 'dt': {"
+ " 'year' : 2023,"
+ " 'month' : 8,"
+ " 'day' : 11"
+ " }"
+ " },"
+ " 'nbOfTxs': '1'"
+ " }"
+ " },"
+ " 'type': 'MX',"
+ " '@xmlns': 'urn:swift:xsd:sese.023.002.01',"
+ " 'identifier': 'sese.023.002.01'"
+ "}";
MxSese02300201 mx = MxSese02300201.fromJson(source);
LocalDate dt = mx.getSctiesSttlmTxInstr().getId().getCreDtTm().getDt();
assertEquals("2023-08-11", dt.toString());
Backward Compatibility version 9
Transitioning from Java 8 to Java 11 in AbstractMX
JSON structure.
As part of the migration from Java 8 to Java 11, AbstractMX
has introduced new methods that ensure backward compatibility, specifically in the context of JSON serialization and deserialization. These methods address the changes in how date-time information is handled, transitioning from the use of XMLGregorianCalendar
in Java 8 to OffsetDateTime
in Java 11.
AbstractMX
JSON V9 Methods
To manage the transition, AbstractMX
provides two methods: fromJsonV9()
and toJsonV9()
. These methods are designed to work with JSON data that was generated using the legacy XMLGregorianCalendar
format while seamlessly transitioning to the newer OffsetDateTime
format.
toJsonV9()
: This method allows you to serialize anAbstractMX
message into a JSON format that is compatible with systems that still expect the olderXMLGregorianCalendar
format. When invoked, this method will structure the JSON data in a way that closely mirrors the legacy format, ensuring that date-time fields are represented in a backward-compatible way.
Example:
This produces a JSON output where date-time fields are serialized in a way that resembles how they were handled with XMLGregorianCalendar
in Java 8.
...
"creDtTm": {
"year": 2022,
"month": 11,
"day": 30,
"timezone": -180,
"hour": 10,
"minute": 43,
"second": 57,
"fractionalSecond": 0.412
},
...
fromJsonV9()
: This method allows the deserialization of JSON data that was generated using the olderXMLGregorianCalendar
format, converting it into the modernOffsetDateTime
format used in Java 11. This ensures that older JSON data can still be processed in a Java 11 environment.
Example:
String json = "{...
"creDtTm": {
"year": 2022,
"month": 11,
"day": 30,
"timezone": -180,
"hour": 10,
"minute": 43,
"second": 57,
"fractionalSecond": 0.412
},
...}"; // JSON data produced from XMLGregorianCalendar
AbstractMX mxMessage = AbstractMX.fromJsonV9(json);
This method parses the JSON, converting legacy date-time fields into OffsetDateTime
, while maintaining compatibility with systems that produced data in the Java 8 format.
This methods allows:
-
Seamless Migration: The
toJsonV9()
andfromJsonV9()
methods ensure that migrating to Java 11 does not disrupt systems that are still using JSON data generated with Java 8. This allows systems to handle both legacy and modern date-time formats without manual intervention. -
Compatibility Across Versions: These methods allow you to maintain compatibility with older systems while adopting the modern
OffsetDateTime
format. Systems that have already transitioned to Java 11 can still interact with services or applications that are based on Java 8 andXMLGregorianCalendar
. -
Preservation of Existing Data: By using
fromJsonV9()
, you can continue to work with existing JSON data that was serialized usingXMLGregorianCalendar
without needing to reformat or update it, reducing the risk of data loss or corruption during migration.
MxSwiftMessage
The MxSwiftMessage
is an alternative model structure, intended for database persistence. The model is actually a
JPA entity. Anyway, this model also provides the toJson()
and fromJson(String json)
methods for conversion to and
from JSON. The conversion can be done as follows:
MxSwiftMessage to Json conversion
In case of need to serialize the message into a JSON structure, the toJson()
method should be used.
The code in the sample below:
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<message>"
+ "<AppHdr xmlns=\"urn:swift:xsd:$ahV10\">"
+ "<From>"
+ " <Type>DN</Type>"
+ " <Id>cn=funds,o=abcdchzzwww,o=swift</Id>"
+ "</From>"
+ "<To>"
+ " <Type>DN</Type>"
+ " <Id>cn=funds,o=dcbadeff,o=swift</Id>"
+ "</To>"
+ " <MsgRef>11308917</MsgRef>"
+ " <CrDate>2013-12-23T15:50:00</CrDate>"
+ "</AppHdr>"
+ "<Document xmlns=\"urn:iso:std:iso:20022:tech:xsd:pacs.008.001.02\" " +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
"xsi:schemaLocation=\"http://www.six-interbank-clearing.com/de/pacs.008.001.02.ch.01 pacs.008.001.02.ch.01.xsd\">"
+ "<FIToFICstmrCdtTrf>"
+ " <GrpHdr>"
+ " <MsgId>MSGID-0001</MsgId>"
+ " <CreDtTm>2001-12-17T09:30:47Z</CreDtTm>"
+ " <NbOfTxs>1</NbOfTxs>"
+ " <IntrBkSttlmDt>2012-01-25</IntrBkSttlmDt>"
+ " <SttlmInf><SttlmMtd>INDA</SttlmMtd></SttlmInf>"
+ " <InstgAgt><FinInstnId><BIC>DDDDCH20DSZ</BIC></FinInstnId></InstgAgt>"
+ " <InstdAgt><FinInstnId><BIC>DRESDEF0VNZ</BIC></FinInstnId></InstdAgt>"
+ " </GrpHdr>"
+ " <CdtTrfTxInf>"
+ " </CdtTrfTxInf>"
+ "</FIToFICstmrCdtTrf>"
+ "</Document>"
+ "</message>";
MxSwiftMessage mx = new MxSwiftMessage(xml);
String jsonMx = mx.toJson();
System.out.println(jsonMx);
Will result in the next json message:
{
'businessProcess': 'pacs',
'functionality': '008',
'variant': '001',
'version': '02',
'identifier': 'pacs.008.001.02',
'sender': 'ABCDCHZZWWW',
'receiver': 'DCBADEFFXXX',
'message': '<?xml version="1.0" encoding="UTF-8"?>
<message>
<AppHdr xmlns="urn:swift:xsd:$ahV10">
<From>
<Type>DN</Type>
<Id>cn=funds,o=abcdchzzwww,o=swift</Id>
</From>
<To>
<Type>DN</Type>
<Id>cn=funds,o=dcbadeff,o=swift</Id>
</To>
<MsgRef>11308917</MsgRef>
<CrDate>2013-12-23T15:50:00</CrDate>
</AppHdr>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pacs.008.001.02"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.six-interbank-clearing.com/de/pacs.008.001.02.ch.01 pacs.008.001.02.ch.01.xsd">
<FIToFICstmrCdtTrf>
<GrpHdr>
<MsgId>MSGID-0001</MsgId>
<CreDtTm>2001-12-17T09:30:47Z</CreDtTm>
<NbOfTxs>1</NbOfTxs>
<IntrBkSttlmDt>2012-01-25</IntrBkSttlmDt>
<SttlmInf>
<SttlmMtd>INDA</SttlmMtd>
</SttlmInf>
<InstgAgt>
<FinInstnId>
<BIC>DDDDCH20DSZ</BIC>
</FinInstnId>
</InstgAgt>
<InstdAgt>
<FinInstnId>
<BIC>DRESDEF0VNZ</BIC>
</FinInstnId>
</InstdAgt>
</GrpHdr>
<CdtTrfTxInf/>
</FIToFICstmrCdtTrf>
</Document>
</message>',
'lastModified': {
'year': 2023,
'month': 8,
'dayOfMonth': 4,
'hourOfDay': 13,
'minute': 26,
'second': 26
},
'creationDate': {
'year': 2023,
'month': 8,
'dayOfMonth': 4,
'hourOfDay': 13,
'minute': 26,
'second': 26
},
'statusTrail': [],
'notes': [],
'properties': {},
'fileFormat': 'MX',
'reference': '11308917',
'revisions': []
}
Json to MxSwiftMessage conversion
In case of need to convert a json formatted message into a model object,
the MxSwiftMessage#fromJson(String json)
method should be used.
String json = "{"
+ " 'businessProcess': 'pacs',"
+ " 'functionality': '008',"
+ " 'variant': '001',"
+ " 'version': '02',"
+ " 'message': '<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<message>"
+ " <AppHdr xmlns:Ah=\"urn:swift:xsd:$ahV10\">"
+ " <From>"
+ " <Type>DN</Type>"
+ " <Id>cn=funds,o=abcdchzzwww,o=swift</Id>"
+ " </From>"
+ " <To>"
+ " <Type>DN</Type>"
+ " <Id>cn=funds,o=dcbadeff,o=swift</Id>"
+ " </To>"
+ " <MsgRef>11308917</MsgRef>"
+ " <CrDate>2013-12-23T15:50:00</CrDate>"
+ " </AppHdr>"
+ " <Document xmlns=\"urn:iso:std:iso:20022:tech:xsd:pacs.008.001.02\" xmlns:xsi= \"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation= \"http://www.six-interbank-clearing.com/de/pacs.008.001.02.ch.01 pacs.008.001.02.ch.01.xsd\">"
+ " <FIToFICstmrCdtTrf>"
+ " <GrpHdr>"
+ " <MsgId>MSGID-0001</MsgId>"
+ " <CreDtTm>2001-12-17T09:30:47Z</CreDtTm>"
+ " <NbOfTxs>1</NbOfTxs>"
+ " <IntrBkSttlmDt>2012-01-25</IntrBkSttlmDt>"
+ " <SttlmInf>"
+ " <SttlmMtd>INDA</SttlmMtd>"
+ " </SttlmInf>"
+ " <InstgAgt>"
+ " <FinInstnId>"
+ " <BIC>DDDDCH20DSZ</BIC>"
+ " </FinInstnId>"
+ " </InstgAgt>"
+ " <InstdAgt>"
+ " <FinInstnId>"
+ " <BIC>DRESDEF0VNZ</BIC>"
+ " </FinInstnId>"
+ " </InstdAgt>"
+ " </GrpHdr>"
+ " <CdtTrfTxInf> </CdtTrfTxInf>"
+ " </FIToFICstmrCdtTrf>"
+ " </Document>"
+ "</message>',"
+ " 'identifier': 'pacs.008.001.02',"
+ " 'sender': 'ABCDCHZZWWW',"
+ " 'receiver': 'DCBADEFFXXX',"
+ " 'lastModified': {"
+ " 'year': 2018,"
+ " 'month': 4,"
+ " 'dayOfMonth': 18,"
+ " 'hourOfDay': 0,"
+ " 'minute': 25,"
+ " 'second': 48"
+ " },"
+ " 'creationDate': {"
+ " 'year': 2018,"
+ " 'month': 4,"
+ " 'dayOfMonth': 18,"
+ " 'hourOfDay': 0,"
+ " 'minute': 25,"
+ " 'second': 48"
+ " },"
+ " 'statusTrail': [],"
+ " 'notes': [],"
+ " 'properties': {},"
+ " 'reference': '11308917',"
+ " 'revisions': []"
+ "}";
MxSwiftMessage mx = MxSwiftMessage.fromJson(json);
assertEquals("001", mx.getVariant());
assertEquals("02", mx.getVersion());
assertEquals("008", mx.getFunctionality());
assertEquals("pacs.008.001.02", mx.getIdentifier());
assertEquals("ABCDCHZZWWW", mx.getSender());
assertEquals("DCBADEFFXXX", mx.getReceiver());
assertEquals("11308917", mx.getReference());
Calendar lastModified = mx.getLastModified();
assertEquals(2018, lastModified.get(Calendar.YEAR));
assertEquals(4, lastModified.get(Calendar.MONTH));
assertEquals(18, lastModified.get(Calendar.DAY_OF_MONTH));
assertEquals(25, lastModified.get(Calendar.MINUTE));
assertEquals(48, lastModified.get(Calendar.SECOND));