Melhor maneira percorrer Json mais complexo e acessar suas propriedades e valores

Bom dia, tenho esse Json de exemplo e gostaria de saber como fazer por exemplo para atingir o nível da propriedade. Exemplo após eu receber esse post eu terei que inicialmente chegar na propriedade results e pegar os valores do personal e name por exemplo. Mas o máximo que consegui até o momento foi: cJsonRet := ::GetContent() (ok, recebo aqui o JSON completo vindo do post) oJson := JsonObject():new() ret := oJson:fromJson(cJsonRet) names := oJson:GetNames() (aqui ele me retorna um array contendo duas posições (ID e CHANGES) e então eu já estou travado pois não conseguir entender uma forma de chegar no conteúdo do changes quem dirá lá no results. Quem puder dar uma explanada eu agradeço. { "id": "4546565767", "changes": [{ "value": { "line": "tecnology", "metadata": { "number": "45459839483", "number_id": "343432226674365576" }, "results": [{ "personal": { "name": "Joyce" }, "id_personal": "HHSGskf84849jkh49hhhHSJHD" }], "status": [{ "from": "90384509485", "id": "YFDNFQjBFNUUzM0VGOTRBNjE4Q0U3AA==", "timestamp": "1655315715", "text": { "body": "aaa ff" }, "type": "text" }] }, "field": "status" }] }

Olá Homero tudo bem? Usei o GetJsonObject para acessar o conteúdo da propriedade changes, em seguida separei results, status e metadata em outros objetos para facilitar o acesso, segue exemplo espero que ajude


/*/{Protheus.doc} processaJson
    (Função responsavel por acessar as informações do json)
    @type  Static Function
    @author Leandro Lemos
    @since 17/06/2022
    @version P12
    @param param_name, param_type, param_descr
    @return return_var, return_type, return_description
    @example
    (examples)
    @see (links_or_references)
/*/
Static Function processaJson()
    Local oJson
    Local cParser
    Local cJson        := ''
    Local oResult
    Local oStatus
    Local oMetadata

    oJson := JsonObject():new()

    //Efetua o parser do JSON que está na string
    montaJson(@cJson)
    cParser := oJson:fromJson(cJson)

    IF ValType(cParser) == "U"

        //Acessando diretamente
        cId := oJson['id']

        //Acessando conteudo da propriedade changes
        ret := oJson:GetJsonObject("changes")
        cField         := ret[1]['field']

        oResult     := ret[1]['value']['results'][1]
        //Acessando algumas propriedades do results
        cPersName := oResult['personal']['name']
        cPersID        := oResult['id_personal']

        oStatus     := ret[1]['value']['status'][1]
        cTimeStamp := oStatus['timestamp']

        oMetadata := ret[1]['value']['metadata']
        nNumber     := oMetadata['number']
        nNumberID    := oMetadata['number_id']

    Else
        Conout("Erro: " + cParser)
    EndIF

    FreeObj(oJson)
    FreeObj(oResult)
    FreeObj(oStatus)
    FreeObj(oMetadata)


Return


/*/{Protheus.doc} montaJson
    (Função responsavel por retornar json no formato string)
    @type  Static Function
    @author Leandro Lemos
    @since 17/06/2022
    @version P12
    @param param_name, param_type, param_descr
    @return return_var, return_type, return_description
    @example
    (examples)
    @see (links_or_references)
/*/
Static Function montaJson(cJson)

    cJson := '{ "id": "4546565767", "changes": [{ "value": { "line": "tecnology", "metadata": { "number": "45459839483", "number_id": "343432226674365576" },'+;
        '"results": [{ "personal": { "name": "Joyce" }, "id_personal": "HHSGskf84849jkh49hhhHSJHD" }], "status": [{ "from": "90384509485", "id": "YFDNFQjBFNUUzM0VGOTRBNjE4Q0U3AA==",'+;
        '"timestamp": "1655315715", "text": { "body": "aaa ff" }, "type": "text" }] },"field": "status" }] }

Return