You are viewing limited content. For full access, please sign in.

Discussion

Discussion

Feature Request: JSON Format Tag

posted on July 7, 2020 Show version history

Hello,

Lately I've had an increasing number of Workflows that use the Web Request to interact with APIs using data collected in a Forms process. The problem I run into is that users sometimes enter characters that are reserved in JSON, such as tab, backslash, or double quotes.

So far the easiest solution has been to just apply regex on the Forms side to prevent those characters from being used. The alternative is to clean them up on the back end, but it can be a huge pain to "sanitize" every form field value before making the API call.

Instead, what I'd love to see is a JSON format tag, similar to the HTML tag, that would automatically clean up reserved JSON characters. That way, I could just use %(Token#"JSON"#) to handle it automatically.

i.e., X"Y\Z would be sent over as X\"Y\\Z

A formatting tag like that would make API calls so much easier because I wouldn't have to worry about all the different ways I might end up with a reserved character; I could just use the tag and call it a day.

5 0
replied on July 14, 2020

Thanks Jason, this seems like a high-value, low-effort feature. I've passed it to the Workflow team for consideration.

2 0
replied on November 3, 2022

Has there been any movement on this? This would be an awesome feature we would love to have as well.

1 0
replied on August 21, 2024

To resurrect this one, I just had an issue where after we upgraded a boolean token from a query was going in as 'True' instead of 'true' when used in workflow web request JSON, which caused it to start failing every time.

It was an easy fix by converting it to lowercase, but this is another example of when a JSON format option could be beneficial; I'd imagine it working somewhat similar to JSON.Encode in ASP.NET web pages.

1 0
replied on August 22, 2024 Show version history

Jason, there are two different standard JSON encodings in the .NET Framework 4.8.1 System.Text.Encodings.Web JavaScriptEncoder class that you can use with System.Text.Json JsonEncodedText.Encode method:

  1. Default
  2. UnsafeRelaxedJsonEscaping

    1. See also: Serialize all characters, especially the "Caution" note

I wrote a quick test program to compare the two with your sample string and a boolean. The Encode() method require string input, and .NET's Boolean.ToString() method returns "True" or "False", so that doesn't help you with the ToLower scenario.

The JsonSerializer.Serialize method returns 'true' as you pass it the Boolean directly without having to first cast it to a string.

What behavior would you expect here?

Output:

Code for reference:

// .NET Framework 4.8.1
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Text.Encodings.Web;
using System.Threading.Tasks;

namespace JsonEncoderDemo
{
    internal class JsonEncoder
    {
        static void Main()
        {
            string inputStr = "X\"Y\\Z";
            bool inputBool = true;

            JsonSerializerOptions jsoDefault = new JsonSerializerOptions() { Encoder = JavaScriptEncoder.Default };
            JsonSerializerOptions jsoUnsafeRelaxed = new JsonSerializerOptions() { Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping };

            string outputStrEncoderDefault = JsonEncodedText.Encode(inputStr, JavaScriptEncoder.Default).ToString();
            string outputStrEncoderUnsafeRelaxed = JsonEncodedText.Encode(inputStr, JavaScriptEncoder.UnsafeRelaxedJsonEscaping).ToString();
            var outputStrSerializedDefault = JsonSerializer.Serialize(inputStr, jsoDefault);
            var outputStrSerializedUnsafeRelaxed = JsonSerializer.Serialize(inputStr, jsoUnsafeRelaxed);

            string outputBoolEncoderDefault = JsonEncodedText.Encode(inputBool.ToString(), JavaScriptEncoder.Default).ToString();
            string outputBoolEncoderUnsafeRelaxed = JsonEncodedText.Encode(inputBool.ToString(), JavaScriptEncoder.UnsafeRelaxedJsonEscaping).ToString();
            var outputBoolSerializedDefault = JsonSerializer.Serialize(inputBool, jsoDefault);
            var outputBoolSerializedUnsafeRelaxed = JsonSerializer.Serialize(inputBool, jsoUnsafeRelaxed);

            Console.WriteLine("Input String:         " + inputStr);
            Console.WriteLine("Encoded (Default):    " + outputStrEncoderDefault);
            Console.WriteLine("Encoded (Relaxed):    " + outputStrEncoderUnsafeRelaxed);
            Console.WriteLine("Serialized (Default): " + outputStrSerializedDefault);
            Console.WriteLine("Serialized (Relaxed): " + outputStrSerializedUnsafeRelaxed);
            Console.WriteLine("");
            Console.WriteLine("Input Bool:           " + inputBool);
            Console.WriteLine("Encoded (Default):    " + outputBoolEncoderDefault);
            Console.WriteLine("Encoded (Relaxed):    " + outputBoolEncoderUnsafeRelaxed);
            Console.WriteLine("Serialized (Default): " + outputBoolSerializedDefault);
            Console.WriteLine("Serialized (Relaxed): " + outputBoolSerializedUnsafeRelaxed);
            Console.WriteLine("");
        }
    }
}

Some good related discussion on Stack Overflow here: 
c# - dotnet core System.Text.Json unescape unicode string - Stack Overflow

0 0
replied on August 22, 2024 Show version history

I suppose the Encode method wasn't an ideal example since I was thinking more about the output in specific scenarios.

Serialized is more accurate, but really I'm just after a way to ensure tokens are in a valid JSON format rather than being output as any particular data type (i.e., true/false/null vs True/False/[NULL or empty]).

I wouldn't expect full serialization of complex objects or anything like that, just a way to ensure the following:

  1. Boolean values return true/false (null when empty)
  2. Reserved characters are escaped in string/text values

 

I think what changed after the update is that I used to get true/false but now I get True/False more like .ToString() in .NET.

In the past I've gotten around the default ToString behavior when setting input values or dynamic JavaScript in .NET MVC views with JSON.Encode like:

Serialization could be overkill for the boolean since all I'd really hope for is a way to ensure it returns true/false/null so the resulting value work in the JSON when:

  1. Has the Boolean tag set
  2. Has a JSON format applied
1 0
replied on August 28, 2024 Show version history

Where does that leave us in terms of the actual .NET Framework function(s) you'd want called for a JSON method? There could be more than one.

The existing Workflow "Encode" token functions are:

0 0
replied on August 28, 2024 Show version history

Hi Sam,

I think maybe I confused the issue.

I'm not looking for any specific .NET functions, just a way to "format" the content so it can be safely used in JSON the same way we can use the HTML format tag for tokens that contain dynamically created HTML.

For example, I use %(Token#HTML#) in an email activity to tell Workflow that the content is HTML and to include it as-is, without escapes, so the email will show something like a link instead of the literal HTML.

 

For JSON, I'm looking for something to tell Workflow "this is for JSON" so I can get JSON-compatible values in dynamic web requests.

For example, say I have 2 tokens, one string and one boolean

StringToken = "Test Data\Token"

BoolToken = True

In a Web Request activity's JSON body field

{
    "Text": "%(StringToken)"
    "Boolean": %(BoolToken)
}

Will currently result in

{
    "Text": "Test Data\Token"
    "Parameter": True
}

But this is invalid JSON and the request will fail because the \ is a reserved character and JSON does not support the title case boolean value.

 

The goal is for this:

{
    "Text": "%(StringToken#JSON#)"
    "Boolean": %(BoolToken#JSON#)
}

to produce this (i.e., ensuring JSON-compatible content)

{
    "Text": "Test Data\\Token"
    "Parameter": true
}

 

1 0
You are not allowed to follow up in this post.

Sign in to reply to this post.