2

I'm using Prowide-Core for SWIFT message handling. At the moment I use the JSON methods to produce human readable versions of my messages if I need to dump them out. This produces output like this:

...
}, {
  "97A" : ":SAFE//0123-0123456-55-000"
}, {
...

I.e. I get alphanumeric codes, like 97A, for the field names.

However it I look at Field97A.java:471 I can see that it (and all other fields) know their more human readable names (Qualifier and Account in the case of 97A).

I've tried looking for some toString() like method that makes use of this information to produce something even more readable than the JSON output but haven't found anything yet.

Is there such a method on SwiftMessage or one of the related classes? Or has someone written something nice that can traverse a message and print it out using the information returned by getComponentLabels() etc?

George Hawkins
  • 37,044
  • 7
  • 30
  • 43

2 Answers2

2

I'm one of the authors. For future reference, in the upcoming SRU2018 release (scheduled for October) we have revamped all the JSON API in all model abstraction layers.

The toJson in SwiftMessage object still produces plain name/value tuples for the Tags. However, in the MTnnn classes, the toJson uses Field to produce JSON with business labels such as:

{   "name": "90A",
    "qualifier": "DEAL",
    "percentageTypeCode": "PRCT",
    "price": "102,713552"
},
{   "name": "36B",
    "qualifier": "ESTT",
    "quantityTypeCode": "AMOR",
    "quantity": "7999999,573"
},
{   "name": "97A",
    "qualifier": "SAFE",
    "account": "0123-0123456-55formatted  
}

Besides the JSON, you can iterate the fields and print formated name and values with the available getLabel and getValueDisplay methods.

For example:

Locale locale = Locale.getDefault();
SwiftMessage sm = SwiftMessage.parse("{1:F01BACOARB1A0B20000000000}{2:I103ADRBNL21XXXXU2}{3:{108:FOOB3926BE868XXX}}{4:\n" +
    ":20:REFERENCE\n" +
    ":23B:CRED\n" +
    ":32A:180730USD1234567,89\n" +
    ":50A:/12345678901234567890\n" +
    "CFIMHKH1XXX\n" +
    ":59:/12345678901234567890\n" +
    "JOE DOE\n" +
    "MyStreet 1234\n" +
    ":71A:OUR\n" +
    "-}");
System.out.println("Sender: " + sm.getSender());
System.out.println("Receiver: " + sm.getReceiver() + "\n");
for (Tag tag : sm.getBlock4().getTags()) {
    Field field = tag.asField();
    System.out.println(Field.getLabel(field.getName(), "103", null, locale));
    System.out.println(field.getValueDisplay(locale) + "\n");
}

Will produce this output:

Sender: BACOARB1A0B2 Receiver: ADRBNL21XXXX

Sender's Reference
REFERENCE

Bank Operation Code
CRED

Value Date/Currency/Interbank Settled Amount
Jul 30, 2018 USD 1,234,567.89

Ordering Customer
12345678901234567890 CFIMHKH1XXX

Beneficiary Customer
12345678901234567890 JOE DOE MyStreet 1234

Details of Charges
OUR

Where components are split and formatted for the locale. And if you also need labels per component, you can further iterate the components like this:

for (Tag tag : sm.getBlock4().getTags()) {
    Field field = tag.asField();
    System.out.println("\n" + Field.getLabel(field.getName(), "103", null, locale));
    for (int component = 1 ; component <= field.componentsSize() ; component++) {
        if (field.getComponent(component) != null) {
            System.out.print(field.getComponentLabel(component) + ": ");
            System.out.println(field.getValueDisplay(component, locale));
        }
    }
}

Pruducing this other output:

Sender's Reference
Reference: REFERENCE

Bank Operation Code
Type: CRED

Value Date/Currency/Interbank Settled Amount
Date: Jul 30, 2018
Currency: USD
Amount: 1,234,567.89

Ordering Customer
Account: 12345678901234567890
BIC: CFIMHKH1XXX

Beneficiary Customer
Account: 12345678901234567890
Name And Address: JOE DOE
Name And Address 2: MyStreet 1234

Details of Charges
Code: OUR

Finally, if you are interested, the Integrator library from Prowide includes out-of-the-box printout visitors to produce HTML, TXT, and XML including structured sequences and BIC expanded with the institution information. You may ask Prowide for a trial.

  • Hi, I couldn't find asField() in the Tag class and giving me error: The method asField() is undefined for the type Tag – thevipulvats Mar 11 '21 at 12:42
  • This is the javadoc for the method: https://www.javadoc.io/static/com.prowidesoftware/pw-swift-core/SRU2020-9.1.3/com/prowidesoftware/swift/model/Tag.html#asField-- which basically does Field.getField(tag). If takes the tag name and creates the specific field instance using reflection. Each field model knows how to parse its plain value into the internal components. – Sebastian Zubrinic Mar 13 '21 at 23:26
0

SwiftTagListBlock provides a toJson method that iterates over Tag objects:

     public String toJson() {
         final StringBuilder sb = new StringBuilder();
         sb.append("[ \n");
         if (this.tags != null && !this.tags.isEmpty()) {
             for (int i=0;i<this.tags.size();i++) {
                 final Tag t = this.tags.get(i);
                 sb.append("{ \"").append(t.getName()).append("\" : \"").append(escapeJson(t.getValue())).append("\" }");
                 if (i+1<this.tags.size()) {
                     sb.append(',');
                 }
                 sb.append('\n');
             }

         }
         sb.append("]");
         return sb.toString();
      }

You could tweak the source code and call the asField() method of Tag, in order to have access to the Field representation and use the information required for your output.

localghost
  • 419
  • 2
  • 6
  • Unfortunately what a field means depends on its context, e.g. field [331](https://github.com/prowide/prowide-core/blob/master/src/main/java/com/prowidesoftware/swift/model/field/Field331.java#L1405) can mean "Session Number", "Date Session Opened", "Time Session Opened", "Date Session Closed" or one of eight further values. I'm guessing it's the block number that one has to keep track of and pass to `getComponentLabel(int)` to get the context appropriate value? – George Hawkins Nov 13 '17 at 15:30
  • I don't think that the swift block number will fit the purpose. The `int` for `getComponentLabel(int)` probably refers to [static identifiers](https://github.com/prowide/prowide-core/blob/master/src/main/java/com/prowidesoftware/swift/model/field/Field331.java#L90) for the components. What is needed is a mapping from a `Field`/`Tag` to the appropriate component number. – localghost Nov 13 '17 at 17:29
  • Component labels are fixed and not context-dependent. For 331; "Session Number", "Date Session Opened", etc... are the individual label for each component within the field. Meaning the different parts of the value when the field parser split it into the internal components. It is not label for the field as a whole. Component numbers are just 1 to n. The number of components in a field is fixed, from the standard, depending on the structure of each field. Field 32A will always be composed by a value date, a currency and an amount, thus will always have 3 components in its model. – Sebastian Zubrinic Mar 13 '21 at 23:40