Search code examples
microsoft-dynamicsdynamics-365navisiondynamics-navbusinesscentral

How to create a web service that accepts a json with an array?


I already know that the "official" way is sending all the entire JSON in a string with unbound actions, but per project specification I need the API to be able to read json arrays in json format.

To be clear with an example, this is the data to be sent to the API:

{
    "Batch": "IC0001",
    "Colors": [
        {
            "Color": "GENERAL",
            "Code": "112",
            "Description": "BERMELLON",
            "RGB": "255,0,0",
            "GroupWeb": "40"
        },
        {
            "Color": "GENERAL",
            "Code": "111",
            "Description": "ROJERAS",
            "RGB": "255,0,0",
            "GroupWeb": "40"
        }
    ]
}

I'm trying to read the JSON with the codeunit "JSON Management":

codeunit 60201 IntegracionPLM
{ 
    procedure ReadColorJSON(data: Text)
    var
        JSONManagement: Codeunit "JSON Management";
        ArrayJSONManagement: Codeunit "JSON Management";
        ObjectJSONManagement: Codeunit "JSON Management";
        i: Integer;
        JsonArrayText: Text;
        ColorJsonObject: Text;
        GrupoColoresText: Text;
        CodigoText: Text;
        DescripcionText: Text;
        ValorRGBText: Text;
        AgrupacionWebText: Text;
    begin
        JSONManagement.InitializeObject(Data);

        if JSONManagement.GetArrayPropertyValueAsStringByName('data', JsonArrayText) then begin
            ArrayJSONManagement.InitializeCollection(JsonArrayText);

            for i := 0 to ArrayJSONManagement.GetCollectionCount() - 1 do begin
                ArrayJSONManagement.GetObjectFromCollectionByIndex(ColorJsonObject, i);
                ObjectJSONManagement.InitializeObject(ColorJsonObject);

                ObjectJSONManagement.GetStringPropertyValueByName('GrupoColores', GrupoColoresText);
                ObjectJSONManagement.GetStringPropertyValueByName('Codigo', CodigoText);
                ObjectJSONManagement.GetStringPropertyValueByName('Descripcion', DescripcionText);
                ObjectJSONManagement.GetStringPropertyValueByName('ValorRGB', ValorRGBText);
                ObjectJSONManagement.GetStringPropertyValueByName('AgrupacionWeb', AgrupacionWebText);

                Message('GrupoColores: %1, Codigo: %2, Descripcion: %3, ValorRGB: %4, AgrupacionWeb: %5', 
                         GrupoColoresText, CodigoText, DescripcionText, ValorRGBText, AgrupacionWebText);
            end;
        end;
    end;
}

But I'm getting this error:

{
    "error": {
        "code": "BadRequest",
        "message": "One or more errors occurred. (One or more errors occurred. (An unexpected 'StartArray' node was found when reading from the JSON reader. A 'StartObject' node was expected.))  CorrelationId:  829669bb-ea16-4703-9ef1-e9431d47928e."
    }
}

The request is not going through. Not even reaching my code.

How can I read a json array from my Business Central web service?


Solution

  • Solved by following this guide: https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/developer/devenv-develop-custom-api

    Step 3 did the trick, creating a page with a part:

    page 50100 "API Car Brand"
    {
        PageType = API;
    
        APIVersion = 'v1.0';
        APIPublisher = 'bctech';
        APIGroup = 'demo';
    
        EntityCaption = 'Car Brand';
        EntitySetCaption = 'Car Brands';
        EntityName = 'carBrand';
        EntitySetName = 'carBrands';
    
        ODataKeyFields = SystemId;
        SourceTable = "Car Brand";
    
        Extensible = false;
        DelayedInsert = true;
    
        layout
        {
            area(content)
            {
                repeater(Group)
                {
                    field(id; Rec.SystemId)
                    {
                        Caption = 'Id';
                        Editable = false;
                    }
    
                    field(name; Rec.Name)
                    {
                        Caption = 'Name';
                    }
                    field(description; Rec.Description)
                    {
                        Caption = 'Description';
                    }
                    field(country; Rec.Country)
                    {
                        Caption = 'Country';
                    }
                }
    
                part(carModels; "API Car Model")
                {
                    Caption = 'Car Models';
                    EntityName = 'carModel';
                    EntitySetName = 'carModels';
                    SubPageLink = "Brand Id" = Field(SystemId);
                }
            }
        }
    }
    

    And it's part:

    page 50101 "API Car Model"
    {
        PageType = API;
    
        APIVersion = 'v1.0';
        APIPublisher = 'bctech';
        APIGroup = 'demo';
    
        EntityCaption = 'Car Model';
        EntitySetCaption = 'Car Models';
        EntityName = 'carModel';
        EntitySetName = 'carModels';
    
        ODataKeyFields = SystemId;
        SourceTable = "Car Model";
    
        Extensible = false;
        DelayedInsert = true;
    
        layout
        {
            area(content)
            {
                repeater(Group)
                {
                    field(id; Rec.SystemId)
                    {
                        Caption = 'Id';
                        Editable = false;
                    }
                    field(name; Rec.Name)
                    {
                        Caption = 'Name';
                    }
                    field(description; Rec.Description)
                    {
                        Caption = 'Description';
                    }
                    field(brandId; Rec."Brand Id")
                    {
                        Caption = 'Brand Id';
                    }
                    field(power; Rec.Power)
                    {
                        Caption = 'Power';
                    }
                    field(fuelType; Rec."Fuel Type")
                    {
                        Caption = 'Fuel Type';
                    }
                }
            }
        }
    }
    

    Then go to Postman or your tool of preference and test this:

    POST https://api.businesscentral.dynamics.com/v2.0/<environmentName>/api/bctech/demo/v1.0/companies(<company id>))/carBrands
    {
        "name": "CARBRAND2",
        "description": "Car Brand 2",
        "country": "Germany",
        "carModels": [{
                        "name": "MODELA",
                        "description": "Model A",
                        "power": 0,
                        "fuelType": "Electric"
                    },
                    {
                        "name": "MODELB",
                        "description": "Model B",
                        "power": 0,
                        "fuelType": "Electric"
                    }]
    }