Pretty Printing a Json Blob for a Message in BC SaaS

Dirk_BourgeoisDirk_Bourgeois Member Posts: 6
edited 2021-09-08 in NAV Tips & Tricks
Built this code for BC SaaS, since we cannot use any DotNet tools, and was getting tired of saving the output and putting it in a Formatting tool to make sense of the one long string..
It's not perfect, but makes stuff readable. Feel free to post a suggestion.
codeunit 50000 "Json Library"
{
    procedure PrettyPrintJsonContent(JsonContent: Text): Text
    var
        jObject: JsonObject;
    begin
        jObject.ReadFrom(JsonContent);
        exit(PrettyPrintJsonContent(jObject));
    end;

    procedure PrettyPrintJsonContent(jObject: JsonObject): Text
    begin
        exit(DoPrettyPrintJsonContent(jObject, 0));
    end;

    local procedure DoPrettyPrintJsonContent(jObject: JsonObject; Indent: Integer): Text;
    var
        tb: TextBuilder;
    begin
        tb.AppendLine(GetIndent(Indent) + '{');

        tb.Append(FormatJsonContent(jObject, Indent));

        tb.AppendLine(GetIndent(Indent) + '}');

        exit(tb.ToText());
    end;

    local procedure FormatJsonContent(jObject: JsonObject; var Indent: Integer): Text;
    var
        ValueContent: Text;
        Counter: Integer;
        i: Integer;
        tb: TextBuilder;
        jArray: JsonArray;
        jToken: JsonToken;
        ValuePair: Label '"%1":"%2"', Locked = true;
    begin
        Indent += 1;

        foreach jToken in jObject.Values do begin
            case (true) of
                jToken.IsArray:
                    begin
                        jArray := jToken.AsArray();
                        tb.AppendLine(GetIndent(Indent) + '"' + GetTokenName(jToken) + '"' + ':' + '[');
                        for i := 0 to (jArray.Count - 1) do begin
                            jArray.Get(i, jToken);
                            tb.Append(DoPrettyPrintJsonContent(jToken.AsObject(), Indent + 1));
                        end;
                        tb.AppendLine(GetIndent(Indent) + ']');
                    end;
                jToken.IsObject:
                    begin
                        tb.AppendLine(GetIndent(Indent) + '"' + GetTokenName(jToken) + '"' + ':');
                        tb.Append(DoPrettyPrintJsonContent(jToken.AsObject(), Indent));
                    end;
                jToken.IsValue:
                    begin
                        Clear(ValueContent);
                        if (not jToken.AsValue().IsNull) and (not jToken.AsValue().IsUndefined) then
                            ValueContent := jToken.AsValue().AsText();
                        ValueContent := GetIndent(Indent) + StrSubstNo(ValuePair, GetTokenName(jToken), ValueContent);
                        if (Counter < (jObject.Values.Count - 1)) then
                            ValueContent += ',';
                        tb.AppendLine(ValueContent);
                    end;
            end;

            Counter += 1;
        end;

        Indent -= 1;

        exit(tb.ToText());
    end;

    procedure GetTokenName(jToken: JsonToken) Output: Text
    begin
        Output := jToken.Path;

        while (StrPos(Output, '.') > 0) do
            Output := CopyStr(Output, StrPos(Output, '.') + 1);

        exit(Output);
    end;

    local procedure GetIndent(Count: Integer) IndentValue: Text
    var
        Spacer: Char;
        i: Integer;
    begin
        Spacer := 12288;
        for i := 1 to Count do
            IndentValue += Spacer;
    end;
}


This in Combination with a Page Blob.HasValue field calling this function on it's DrillDown Trigger:
    field("Response Content"; Rec."Response Content".HasValue)
    {
        ApplicationArea = All;
        Caption = 'Response Content';
        ToolTip = 'Specifies the value of the "Response Content" field';
        Editable = false;
    
        trigger OnDrillDown()
        begin
            MessageBlobContent(Rec, Rec.FieldNo("Response Content"), true, true);
        end;
    }
    procedure MessageBlobContent(RecordVar: Variant; FieldID: Integer; JsonContent: Boolean; EnableSaveOption: Boolean)
    var
        TempBlob: Codeunit "Temp Blob";
        RecRef: RecordRef;
        FldRef: FieldRef;
        DataStream: InStream;
        Content: Text;
        TargetDirectory: Text;
        TargetFilename: Text;
        ConfirmSaveLbl: Label 'Would you like to Save this content to a File ?\\%1', Comment = '%1 = Blob Content';
        SelectTargetCaptionLbl: Label 'Select Destination';
        FileTypeLbl: Label 'Json File *.json| *.json';
        FilenameFormatTok: Label 'BlobContent-%1.json', Locked = true;
    begin
        RecRef.GetTable(RecordVar);
        FldRef := RecRef.Field(FieldID);
        if (FldRef.Type <> FieldType::Blob) then
            exit;

        TempBlob.FromRecordRef(RecRef, FieldID);
        if (not TempBlob.HasValue()) then
            exit;

        TempBlob.CreateInStream(DataStream);
        DataStream.ReadText(Content);
        if (Content = '') then
            exit;

        if (JsonContent) then
            Content := JsonLibrary.PrettyPrintJsonContent(Content);

        if (not EnableSaveOption) then begin
            Message(Content);
            exit;
        end;

        if (not Confirm(StrSubstNo(ConfirmSaveLbl, Content), false)) then
            exit;

        TargetFilename := StrSubstNo(FilenameFormatTok, Format(CurrentDateTime(), 0, '<Year4><Month,2><Day,2>-<Hours24><Minutes,2><Seconds,2>'));
        DownloadFromStream(DataStream, SelectTargetCaptionLbl, TargetDirectory, FileTypeLbl, TargetFilename);
    end;


Hope this serves you well..

Comments

  • JuhlJuhl Member Posts: 728
    use WriteObjectToString() to beautify json from the json Management
    Follow me on my blog juhl.blog
Sign In or Register to comment.