dataweavemule4

Append to a matched regex string


Using dataweave with import * from dw::core::Strings

I have converted a JSON payload into a plain text string. I am able to use the Java functions replaceAll, match, etc. with a regex pattern to find all dates in the format YYYY-MM-DD. However, in addition to locating all instances of the pattern, I want to append the static value "as Date" to each of these matches without overwriting the original date values.

For example, if the input is

[{"customer": "ACME inc", "FirstOrderDate": "2025-01-01", "LastOrderDate": "2025-05-25", "ZipCode": "01234"}]

Output should be:

[{"customer": "ACME inc", "FirstOrderDate": "2025-01-01" as Date, "LastOrderDate": "2025-05-25" as Date, "ZipCode": "01234"}]

Solution

  • The expected output is not fully clear, however I will try to explain some methods to achieve something similar. If you want to test if a String is a Date then testing with regular expression is not the correct way to validate. It will not be possible to test all the nuances of date handling. The right way to test is to try to convert to an actual Date and see what happens:

    %dw 2.0
    output application/dw
    import try, orElse from dw::Runtime
    var testData=[{"customer": "ACME inc", "FirstOrderDate": "2025-01-01", "LastOrderDate": "2025-05-25", "ZipCode": "01234"}]
    ---
    testData map (
        $ mapObject ((value, key) 
            -> (key): if(try(() -> value as Date {format: "yyyy-MM-dd"}).success) 
                        value ++ " as Date" 
                      else 
                      value
            )
    )
    

    Output:

    [
      {
        customer: "ACME inc",
        FirstOrderDate: "2025-01-01 as Date",
        LastOrderDate: "2025-05-25 as Date",
        ZipCode: "01234"
      }
    ]
    

    I'm just adding " as Date" as a literal string to the value as an example since it is not possible to do what you are requesting. I use the map() function to transform each item in the input array and mapObject() is for transforming each key-value in the item. Note the usage of the application/dw output format for debugging. It shows us the types of the data more clearly but it should not be used in real life scripts.

    The try() function let us try to execute an operation and confirm if it succeeded or failed.

    As another example, if instead you want to transform each date in a string into a DataWeave Date the script is even simpler, since the orElse() function allows as to return something else if the try fails, which we can use to return the original value:

    %dw 2.0
    output application/dw
    import try, orElse from dw::Runtime
    var testData=[{"customer": "ACME inc", "FirstOrderDate": "2025-01-01", "LastOrderDate": "2025-05-25", "ZipCode": "01234"}]
    ---
    testData map (
        $ mapObject ((value, key) -> (key): try(() -> value as Date {format: "yyyy-MM-dd"}) orElse value)
    )
    

    Output:

    [
      {
        customer: "ACME inc",
        FirstOrderDate: |2025-01-01| as Date {format: "yyyy-MM-dd"},
        LastOrderDate: |2025-05-25| as Date {format: "yyyy-MM-dd"},
        ZipCode: "01234"
      }
    ]
    

    However that only will be useful for formats that have Date types like DW or Java. If the output is set to JSON the dates will be converted back to Strings since JSON doesn't has a date type:

    [
      {
        "customer": "ACME inc",
        "FirstOrderDate": "2025-01-01",
        "LastOrderDate": "2025-05-25",
        "ZipCode": "01234"
      }
    ]
    

    A clarification about the DW output: while in the visualization it is showing as Date... it doesn't mean that something was added as part of the value. It is only the format showing debugging information of the type.

    If the intention is to convert to date and/or time types to be used later in the application then use Java as the output format to avoid unneeded transformations.