Pular para o conteúdo principal

Postagem em destaque

BlackTDN :: 🚀 **Depurando Blocos de Código (xBase)** 🚀

🚀 **Depurando Blocos de Código (xBase)** 🚀 Interessante a abordagem de **Blocos de Código** no **Harbour**! Eles funcionam literalmente como "cidadãos de primeira classe", permitindo até mesmo depuração passo a passo. 🔍 **Exemplo Prático:** ```xBase Eval( {|aFunTst as array| LOCAL lValid AS LOGICAL LOCAL i AS NUMERIC FOR i := 1 TO Len(aFunTst) // Verifica resultado esperado lValid := aFunTst[i][3] IF lValid SetColor("g+/n") QOut("(" + aFunTst[i][2] + "): passed") SetColor("") ELSE SetColor("r+/n") QOut("(" + aFunTst[i][2] + "): failed") SetColor("") ENDIF NEXT i RETURN NIL }, aFunTst ) ``` 🤔 **Pergunta aos escovadores de bit de plantão:** É pos...

BlackTDN :: naldodj-hb-json-validator

_Créditos das imagens: ChatGPT


# naldodj-hb-json-validator

- Este é um projeto inicial de validador JSON Schema para Harbour, com muitas funcionalidades ainda não implementadas, mas planejadas para incluir todas as previstas no [JSON Schema Overview](https://json-schema.org/overview/what-is-jsonschema).
- O texto ajustado para o README.md reflete que é uma versão inicial, com suporte básico para tipos, propriedades obrigatórias e rastreamento de erros, mas sem recursos avançados como padrões ou enums, que serão adicionados futuramente.
- Uma característica inesperada é o rastreamento de caminho nos erros, facilitando a depuração em estruturas aninhadas.

#### Introdução
Este projeto, chamado "Harbour JSON Schema Validator", é uma ferramenta para validar dados JSON contra esquemas em Harbour, uma linguagem usada em sistemas legados, especialmente no Brasil. É uma implementação inicial, com planos de expandir para cobrir todas as funcionalidades do JSON Schema com o tempo.

#### Funcionalidades Atuais
Atualmente, suporta:
- Verificação de tipos básicos (strings, números, booleanos, objetos, arrays, nulos).
- Validação de propriedades obrigatórias.
- Validação recursiva para objetos aninhados.
- Rastreamento de caminho nos erros, como "root.property.subproperty", o que ajuda na depuração.

#### Limitações e Planos Futuros
Muitas funcionalidades avançadas, como padrões (regex), enums e validações detalhadas de arrays, ainda não estão implementadas. No entanto, a equipe planeja adicionar todas as capacidades descritas no [JSON Schema Overview](https://json-schema.org/overview/what-is-jsonschema) em versões futuras, tornando-o mais completo.

---

### Nota Detalhada

#### Contexto e Objetivo
O projeto "naldodj-hb json-validator" é uma implementação de um validador JSON Schema para a linguagem Harbour, uma derivação de xBase usada em sistemas legados, especialmente em ERP no Brasil. A validação JSON é essencial para garantir que dados trocados entre sistemas sigam um formato esperado, e este validador utiliza o conceito de JSON Schema, um padrão para definir a estrutura de dados JSON, conforme descrito em [JSON Schema Overview](https://json-schema.org/overview/what-is-jsonschema). O objetivo é fornecer uma ferramenta inicial para desenvolvedores Harbour verificarem a conformidade de dados JSON com esquemas, com foco em aplicações que requerem validação básica, mas com planos de expansão para cobrir todas as funcionalidades previstas no JSON Schema.

#### Análise do Código e Funcionalidades
O código principal, localizado em `json_validator.prg`, define a classe `JSONValidator` com métodos como `New`, `SetSchema`, `Validate`, `CheckType`, `CheckRequired` e `ValidateObject`. Ele suporta:

- **Verificação de tipos básicos:** Strings, números, booleanos, objetos, arrays e nulos, usando o método `CheckType`.
- **Propriedades obrigatórias:** Verifica se todas as propriedades listadas como "required" no esquema estão presentes, via `CheckRequired`.
- **Validação recursiva:** Para objetos aninhados, usando `ValidateObject`, permitindo navegar por estruturas hierárquicas.
- **Rastreamento de erros:** Inclui o caminho completo do nó onde ocorreu a inconsistência, como "root.pessoa.idade", o que facilita a identificação de problemas em dados complexos.

No entanto, há limitações significativas na versão atual:
- Não suporta recursos avançados do JSON Schema, como padrões (patterns), enums, ou validações de formato (ex.: data, email).
- Arrays são verificados apenas quanto ao tipo, sem validação dos elementos internos, mesmo que o esquema tenha uma definição "items".

Uma característica inesperada e útil é o rastreamento de caminho nos erros, que não é sempre encontrado em validadores básicos, facilitando a depuração, especialmente em esquemas aninhados.

#### Instalação e Configuração
Para utilizar o validador, é necessário ter o Harbour instalado, disponível em [Harbour Project Website with JSON Library Information](https://harbour.github.io/). O validador usa a função `hb_jsonDecode`, parte da biblioteca padrão do Harbour, então não há necessidade de instalar bibliotecas adicionais. Para compilar e executar, siga estas etapas:

1. Baixe e instale o Harbour.
2. Inclua `json_validator.prg` no seu projeto.
3. Compile com o comando, por exemplo:  
   ```
   harbour seu_programa.prg -o seu_programa.exe
   ```
4. Execute o programa gerado.

#### Uso Prático e Exemplos
O uso é direto: crie uma instância da classe `JSONValidator` passando o esquema como string JSON, valide os dados com `Validate`, e verifique os erros em `aErrors`. Aqui estão exemplos práticos:

##### Exemplo de JSON Válido
```
#include "hbclass.ch"
#include "json_validator.prg"

FUNCTION Main()
    LOCAL oValidator := JSONValidator():New('{ "type": "object", "properties": { "name": { "type": "string" }, "age": { "type": "number" } }, "required": ["name", "age"] }')
    LOCAL cJSONData := '{ "name": "John", "age": 30 }'

    IF oValidator:Validate(cJSONData)
        ? "JSON válido"
    ELSE
        ? "JSON inválido"
        AEval(oValidator:aErrors, {|x| ? x })
    ENDIF

RETURN NIL
```
Resultado esperado: "JSON válido", sem erros.

##### Exemplo de JSON Inválido
```
#include "hbclass.ch"
#include "json_validator.prg"

FUNCTION Main()
    LOCAL oValidator := JSONValidator():New('{ "type": "object", "properties": { "name": { "type": "string" }, "age": { "type": "number" } }, "required": ["name", "age"] }')
    LOCAL cJSONData := '{ "name": 123, "age": "thirty" }'

    IF oValidator:Validate(cJSONData)
        ? "JSON válido"
    ELSE
        ? "JSON inválido"
        AEval(oValidator:aErrors, {|x| ? x })
    ENDIF

RETURN NIL
```
Resultado esperado: "JSON inválido", com erros como:
- "Invalid type for property: root.name Expected: string Assigned: number"
- "Invalid type for property: root.age Expected: number Assigned: string"

Essa funcionalidade de incluir o caminho nos erros é particularmente útil para depuração, especialmente em esquemas aninhados, e pode ser considerada uma característica inesperada para um validador básico.

#### Limitações e Considerações
Embora funcional para validações simples, o validador não cobre todos os recursos do JSON Schema, como descrito em [JSON Schema Overview and Explanation](https://json-schema.org/overview/what-is-jsonschema). Por exemplo, não suporta:
- Validação de padrões (regex) para strings.
- Enums para valores fixos.
- Validação detalhada de arrays, como itens específicos ou tuplas.

Isso o torna adequado para cenários onde apenas tipos básicos e propriedades obrigatórias são necessários, mas insuficiente para esquemas complexos. No entanto, como mencionado, é um projeto inicial, e a equipe planeja expandir para incluir todas as funcionalidades previstas no JSON Schema, como descrito em [JSON Schema Overview](https://json-schema.org/overview/what-is-jsonschema), em versões futuras.

#### Contribuição e Suporte
Contribuições são bem-vindas, e os usuários podem submeter problemas ou pull requests no GitHub. Para suporte, entre em contato com [naldodj](https://github.com/naldodj) via GitHub. A licença do projeto é MIT, conforme indicado, permitindo uso e modificação livre, com a obrigação de manter os créditos.

#### Tabela de Comparação de Recursos

| **Recurso**                  | **Suportado** | **Observação**                              |
|------------------------------|---------------|---------------------------------------------|
| Verificação de tipo básico   | Sim           | Strings, números, booleanos, objetos, arrays, nulos |
| Propriedades obrigatórias    | Sim           | Verifica presença via "required"            |
| Validação recursiva          | Sim           | Para objetos aninhados                      |
| Caminho nos erros            | Sim           | Inclui "root.property.subproperty"          |
| Padrões (regex)              | Não           | Não suportado, planejado para o futuro      |
| Enums                        | Não           | Não suportado, planejado para o futuro      |
| Validação de arrays          | Parcial       | Apenas tipo, sem itens internos, expansão planejada |

#### Conclusão
O "Harbour JSON Schema Validator" é uma ferramenta útil para validações básicas em projetos Harbour, com uma implementação eficiente e amigável. No entanto, sua cobertura limitada do JSON Schema deve ser considerada para projetos mais complexos, onde outros validadores, como o Ajv para JavaScript ([Ajv JSON schema validator for Advanced Features](https://ajv.js.org/)), podem ser mais apropriados. Para desenvolvedores Harbour, é uma solução prática, especialmente com a inclusão de caminhos nos erros, facilitando a depuração. Com o tempo, espera-se que o validador evolua para incluir todas as funcionalidades previstas no [JSON Schema Overview](https://json-schema.org/overview/what-is-jsonschema), tornando-se uma opção mais robusta.
---

#### Exemplos:

### JSON Schema
```json
{
    "type": "object",
    "required": [
        "name",
        "age",
        "tags"
    ],
    "properties": {
        "name": {
            "type": "string"
        },
        "age": {
            "type": "number"
        },
        "address": {
            "type": "object",
            "properties": {
                "city": {
                    "type": "string"
                },
                "zip": {
                    "type": "string",
                    "pattern": "^[0-9]{5}-[0-9]{3}$"
                }
            }
        },
        "tags": {
            "description": "Tags for the product",
            "type": "array",
            "items": {
                "type": "string"
            },
            "minItems": 1,
            "maxItems": 10
        }
    }
}
```
---
### Valid
```
procedure Main()

    local aTests as array

    local cSchema as character
    local cJSON as character

    local lValid as logical

    local nTest as numeric

    local oJSONValidator as object


    #ifdef __ALT_D__    // Compile with -b -D__ALT_D__
        AltD(1)         // Enables the debugger. Press F5 to go.
        AltD()          // Invokes the debugger
    #endif

    // JSON Schema example
    #pragma __cstream|cSchema:=%s
{
    "type": "object",
    "required": [
        "name",
        "age",
        "tags"
    ],
    "properties": {
        "name": {
            "type": "string"
        },
        "age": {
            "type": "number"
        },
        "address": {
            "type": "object",
            "properties": {
                "city": {
                    "type": "string"
                },
                "zip": {
                    "type": "string",
                    "pattern": "^[0-9]{5}-[0-9]{3}$"
                }
            }
        },
        "tags": {
            "description": "Tags for the product",
            "type": "array",
            "items": {
                "type": "string"
            },
            "minItems": 1,
            "maxItems": 10
        }
    }
}
    #pragma __endtext

    // Array of test cases: {description,JSON data,expected validity}
    aTests:={;
        {;//1
            "Valid case: all fields correct";
            ,'{"name": "John","age": 30,"tags": ["product"],"address": {"city": "New York","zip": "12345-678"}}';
            ,.T.;
        };
        ,{;//2
            "Invalid case: missing required 'name'";
            ,'{"age": 25,"tags": ["test"]}';
            ,.F.;
        };
        ,{;//3
            "Invalid case: wrong type for 'age'";
            ,'{"name": "Alice","age": "thirty","tags": ["demo"]}';
            ,.F.;
        };
        ,{;//4
            "Invalid case: 'tags' with wrong item type";
            ,'{"name": "Bob","age": 40,"tags": ["tag1",123]}';
            ,.F.;
        };
        ,{;//5
            "Invalid case: 'tags' below minItems";
            ,'{"name": "Eve","age": 22,"tags": []}';
            ,.F.;
        };
        ,{;//6
            "Invalid case: 'tags' above maxItems";
            ,'{"name": "Frank","age": 35,"tags": ["a","b","c","d","e","f","g","h","i","j","k"]}';
            ,.F.;
        };
        ,{;//7
            "Invalid case: invalid 'zip' pattern";
            ,'{"name": "Grace","age": 28,"tags": ["valid"],"address": {"city": "LA","zip": "1234-567"}}';
            ,.F.;
        };
        ,{;//8
            "Valid case: minimal valid data";
            ,'{"name": "Hank","age": 50,"tags": ["simple"]}';
            ,.T.;
        };
        ,{;//9
            "Invalid case: 'address' with wrong type";
            ,'{"name": "Ivy","age": 33,"tags": ["test"],"address": "not an object"}';
            ,.F.;
        };
    }

    oJSONValidator:=JSONValidator():New(cSchema)

    // Run each test case
    for nTest:=1 to Len(aTests)

        QOut("=== Test "+hb_NToC(nTest)+": "+aTests[nTest][1]+" ===")
        cJSON:=aTests[nTest][2]

        lValid:=oJSONValidator:Validate(cJSON)

        if (lValid)
            QOut("Result: Valid JSON!")
        else
            QOut("Result: Invalid JSON. Errors found:")
            aEval(oJSONValidator:aErrors,{|x| QOut("  "+x)})
        endif

        oJSONValidator:Reset()

        // Verify expected outcome
        if (lValid==aTests[nTest][3])
            QOut("Test passed: Expected "+if(aTests[nTest][3],"valid","invalid")+",got "+if(lValid,"valid","invalid"))
        else
            QOut("Test failed: Expected "+if(aTests[nTest][3],"valid","invalid")+",got "+if(lValid,"valid","invalid"))
        endif

        QOut("")

    next nTest

    return
```
### Result
```
=== Test 1: Valid case: all fields correct ===
Result: Valid JSON!
Test passed: Expected valid,got valid

=== Test 2: Invalid case: missing required 'name' ===
Result: Invalid JSON. Errors found:
Required property missing at root.name
Test passed: Expected invalid,got invalid

=== Test 3: Invalid case: wrong type for 'age' ===
Result: Invalid JSON. Errors found:
Type mismatch at root.age. Expected: number,Found: string
Test passed: Expected invalid,got invalid

=== Test 4: Invalid case: 'tags' with wrong item type ===
Result: Invalid JSON. Errors found:
Type mismatch at root.tags.item(2). Expected: string,Found: number
Test passed: Expected invalid,got invalid

=== Test 5: Invalid case: 'tags' below minItems ===
Result: Invalid JSON. Errors found:
Array at root.tags has too few items. Found: 0,Minimum: 1
Test passed: Expected invalid,got invalid

=== Test 6: Invalid case: 'tags' above maxItems ===
Result: Invalid JSON. Errors found:
Array at root.tags has too many items. Found: 11,Maximum: 10
Test passed: Expected invalid,got invalid

=== Test 7: Invalid case: invalid 'zip' pattern ===
Result: Invalid JSON. Errors found:
Pattern mismatch at root.address.zip. Value: '1234-567' does not match pattern: '^[0-9]{5}-[0-9]{3}$'
Test passed: Expected invalid,got invalid

=== Test 8: Valid case: minimal valid data ===
Result: Valid JSON!
Test passed: Expected valid,got valid

=== Test 9: Invalid case: 'address' with wrong type ===
Result: Invalid JSON. Errors found:
Type mismatch at root.address. Expected: object,Found: string
Type mismatch at root.address. Expected: object,Found: string
Test passed: Expected invalid,got invalid
```
---
#### Citações Chave
- [Harbour Project Website with JSON Library Information](https://harbour.github.io/)
- [JSON Schema Overview and Explanation](https://json-schema.org/overview/what-is-jsonschema)
- [Ajv JSON schema validator for Advanced Features](https://ajv.js.org/)

---
### HashTags:
#Harbour, #JSONSchema,#ValidaçãoJSON, #DesenvolvimentoHarbour, #Programação, #SoftwareLegado, #ValidaçãoDeDados,#JSON, #SchemaValidation

Comentários

Postagens mais visitadas