Classe base para criação de adapters utilizados em serviços REST suportando filtros de paginação e filtros baseados no padrão oData.
Descrição
Método construtor da classe
Parâmetros:
Nome | Tipo | Descrição |
---|---|---|
cVerb | Carácter | Verbo Rest utilizado no adapter |
lList | Lógico | Se irá listar o json |
Retorno Logico, Se foi construído corretamente
Descrição
Adiciona campo a campo as configurações de campos utilizado no Adapter
Parâmetros:
Nome | Tipo | Descrição |
---|---|---|
cFieldJson | Carácter | Nome do campo no objeto Json |
cFieldQuery | Carácter | Nome do campo que será utilizado no ResultSet |
lJsonField | Lógico | Se .T. informa que o campo será exportado ao Json |
lFixed | Lógico | Se .T. informa que o campo não pode ser removido pelo FIELDS do QueryParam |
aStruct | Array | Vetor com a estrutura do campo no padrão {"CAMPO", "TIPO", Tamanho, Decimal}, caso não seja informada a estrutura, utiliza como base o dicionário SX3 |
cRenameField | Carácter | Determina o nome real do campo na tabela, para o caso de identificadores ambíguos na query |
O parâmetro
|
Descrição
Informa a query para a geração do Json
Parâmetros
Nome | Tipo | Descrição |
---|---|---|
cQuery | Carácter | Query para geração do Json |
Deverá ser utilizado os Id's:
#QueryFields# Campos do SELECT, existe tratamento para o FIELDS no QueryParam
#QueryWhere# Condições do WHERE, existe tratamento para FILTER no QueryParam
Faz o set da condição de filtro utilizada para ordenação do ResultSet, substitui o id #QueryWhere#
Parâmetros
Nome | Tipo | Descrição |
---|---|---|
cWhere | Carácter | String contendo as condições do where para o ResultSet, substitui o id #QueryWhere# |
Descrição
Faz o set da condição padrão utilizada para ordenação do ResultSet
Parâmetros
Nome | Tipo | Descrição |
---|---|---|
cOrder | Carácter | String contendo a ordenação que irá ser utilizada no ResultSet |
Descrição
String contendo a ordenação informada via QueryParam
Parâmetros
Nome | Tipo | Descrição |
---|---|---|
cOrder | Carácter | String contendo a ordenação que irá ser utilizada no ResultSet. Obs.: Adicione "-" a esquera do cOrder para ordenar decrescente (ex.: "-filial"). |
Descrição
Informa os campos que serão utilizados para geração do Json
Parâmetros
Nome | Tipo | Descrição |
---|---|---|
cFields | Carácter | Campos que serão exportados para o Json, utilizado para setar os campos informados via QueryParam |
Descrição
Realiza o parse dos ids #QueryFields# e #QueryWhere# gerando o ResultSet
Parâmetros
Nome | Tipo | Descrição |
---|---|---|
lUseTmpTable | Logico | Força o uso de tabela temporária, mesmo para os bancos com tratamento para geração de paginação via banco |
Retorno Logico, Retorna se a execução foi realizada com sucesso
Descrição
Método chamado linha a linha do ResultSet para geração do Json
Descrição
Configura qual pagina sera retornada pelo adapter
Parâmetros
Nome | Tipo | Descrição |
---|---|---|
nPage | Numérico | Número da pagina a ser retornada |
Descrição
Configura o tamanho da pagina
Parâmetros
Nome | Tipo | Descrição |
---|---|---|
nPageSize | Numérico | Tamanho da página |
Descrição
Faz a definição do filtro informado via parâmetros de query.
Parâmetros
Nome | Tipo | Descrição |
---|---|---|
aUrlFilter | Array | Filtro via QueryParam |
O parâmetro aUrlFilter
precisa seguir o formato do array da propriedade aQueryString
do Rest Advpl.
No Rest Advpl este array é uma lista de outros array com duas posições, sendo a primeira posição a chave do parâmetro de query e a segunda posição o valor.
// filtros simples // a requição com: ?propriedade1=valor1&propriedade2=valor2 // exigiria o array como aUrlFilter := { ; {"propriedade1", "valor1"},; {"propriedade2", "valor2"} ; } self:SetUrlFilter(aUrlFilter) // filtro complexos // ?filter=propriedade1 eq 'valor1' and propriedade2 eq 'valor2' aUrlFilter := { ; {"FILTER", "propriedade1 eq 'valor1' and propriedade2 eq 'valor2'"}; } self:SetUrlFilter(aUrlFilter) // Rest Advpl // Essa versão do Rest já possui preparado um array com os parâmetros de query no formato adequado // Com isso é possível indicar diretamento o atributo da classe aQueryString self:SetUrlFilter(self:aQueryString) |
Descrição
Permite configurar o nome da propriedade de retorno dos itens da listagem do verbo GET.
Por padrão, o JSON retornado tem a propriedade items, esse método permite trocar o nome dessa propriedade.
Parâmetros
Nome | Tipo | Descrição |
---|---|---|
cPropItems | Carácter | Nome da propriedade de retorno dos itens no JSON de listagem do verbo GET do adapter |
Exemplo
oAdapter:SetStyleReturn("data")
Observação
Esse método está disponível somente para lib igual ou superior a 20221010
Descrição
Irá retornar o Json
Retorno Carácter, Resposta da API
Descrição
Indica que as propriedades do json são case sensitive
Exemplo
oAdapter:setIsCaseSensitive(.T.)
Observação
Esse método está disponível somente para lib igual ou superior a 20230515
Descrição
Filtros que são suportados pela classe, esses podem ser informados durante o consumo da API.
Lista
Observação
Alguns filtros foram implementados em datas diferentes de outros, logo é bom verificar qual filtro está disponível conforma data de sua lib.
O campo data pode ter comportamentos diferentes por conta do dado ser gravado no banco de dados como character.
#include 'totvs.ch' #include 'parmtype.ch' //------------------------------------------------------------------- /*/{Protheus.doc} PrdAdapter Classe Adapter para o serviço @author Anderson Toledo /*/ //------------------------------------------------------------------- CLASS PrdAdapter FROM FWAdapterBaseV2 METHOD New() METHOD GetListProd() EndClass Method New( cVerb ) CLASS PrdAdapter _Super:New( cVerb, .T. ) return Method GetListProd( ) CLASS PrdAdapter Local aArea AS ARRAY Local cWhere AS CHAR aArea := FwGetArea() //Adiciona o mapa de campos Json/ResultSet AddMapFields( self ) //Informa a Query a ser utilizada pela API ::SetQuery( GetQuery() ) //Informa a clausula Where da Query cWhere := " B1_FILIAL = '"+ FWxFilial('SB1') +"' AND SB1.D_E_L_E_T_ = ' '" ::SetWhere( cWhere ) //Informa a ordenação padrão a ser Utilizada pela Query ::SetOrder( "B1_COD" ) //Executa a consulta, se retornar .T. tudo ocorreu conforme esperado If ::Execute() // Gera o arquivo Json com o retorno da Query ::FillGetResponse() EndIf FwrestArea(aArea) Return Static Function AddMapFields( oSelf ) oSelf:AddMapFields( 'CODE' , 'B1_COD' , .T., .T., { 'B1_COD', 'C', TamSX3( 'B1_COD' )[1], 0 } ) oSelf:AddMapFields( 'DESCRIPTION' , 'B1_DESC' , .T., .F., { 'B1_DESC', 'C', TamSX3( 'B1_DESC' )[1], 0 } ) oSelf:AddMapFields( 'GROUP' , 'B1_GRUPO', .T., .F., { 'B1_GRUPO', 'C', TamSX3( 'B1_GRUPO' )[1], 0 } ) oSelf:AddMapFields( 'GROUPDESCRIPTION' , 'BM_DESC' , .T., .F., { 'BM_DESC', 'C', TamSX3( 'BM_DESC' )[1], 0 } ) Return Static Function GetQuery() Local cQuery AS CHARACTER //Obtem a ordem informada na requisição, a query exterior SEMPRE deve ter o id #QueryFields# ao invés dos campos fixos //necessáriamente não precisa ser uma subquery, desde que não contenha agregadores no retorno ( SUM, MAX... ) //o id #QueryWhere# é onde será inserido o clausula Where informado no método SetWhere() cQuery := " SELECT #QueryFields#" cQuery += " FROM " + RetSqlName( 'SB1' ) + " SB1 " cQuery += " LEFT JOIN " + RetSqlName( 'SBM' ) + " SBM" cQuery += " ON B1_GRUPO = BM_GRUPO" cQuery += " AND BM_FILIAL = '"+ FWxFilial( 'SBM' ) +"'" cQuery += " AND SBM.D_E_L_E_T_ = ' '" cQuery += " WHERE #QueryWhere#" Return cQuery |
#include "totvs.ch" #include "restful.ch" //------------------------------------------------------------------- /*/{Protheus.doc} products Declaração do ws products @author Anderson Toledo /*/ //------------------------------------------------------------------- WSRESTFUL products DESCRIPTION 'endpoint products API' FORMAT "application/json,text/html" WSDATA Page AS INTEGER OPTIONAL WSDATA PageSize AS INTEGER OPTIONAL WSDATA Order AS CHARACTER OPTIONAL WSDATA Fields AS CHARACTER OPTIONAL WSMETHOD GET ProdList; DESCRIPTION "Retorna uma lista de produtos"; WSSYNTAX "/api/v1/products" ; PATH "/api/v1/products" ; PRODUCES APPLICATION_JSON END WSRESTFUL WSMETHOD GET ProdList QUERYPARAM Page WSREST products Return getPrdList(self) Static Function getPrdList( oWS ) Local lRet as logical Local oProd as object DEFAULT oWS:Page := 1 DEFAULT oWS:PageSize := 10 DEFAULT oWS:Fields := "" lRet := .T. //PrdAdapter será nossa classe que implementa fornecer os dados para o WS // O primeiro parametro indica que iremos tratar o método GET oProd := PrdAdapter():new( 'GET' ) //o método setPage indica qual página deveremos retornar //ex.: nossa consulta tem como resultado 100 produtos, e retornamos sempre uma listagem de 10 itens por página. // a página 1 retorna os itens de 1 a 10 // a página 2 retorna os itens de 11 a 20 // e assim até chegar ao final de nossa listagem de 100 produtos oProd:setPage(oWS:Page) // setPageSize indica que nossa página terá no máximo 10 itens oProd:setPageSize(oWS:PageSize) // SetOrderQuery indica a ordem definida por querystring oProd:SetOrderQuery(oWS:Order) // setUrlFilter indica o filtro querystring recebido (pode se utilizar um filtro oData) oProd:SetUrlFilter(oWS:aQueryString ) // SetFields indica os campos que serão retornados via querystring oProd:SetFields( oWS:Fields ) // Esse método irá processar as informações oProd:GetListProd() //Se tudo ocorreu bem, retorna os dados via Json If oProd:lOk oWS:SetResponse(oProd:getJSONResponse()) Else //Ou retorna o erro encontrado durante o processamento SetRestFault(oProd:GetCode(),oProd:GetMessage()) lRet := .F. EndIf //faz a desalocação de objetos e arrays utilizados oProd:DeActivate() oProd := nil Return lRet |
http://localhost:8080/teste/rest/api/v1/products?pagesize=1&page=3 |
http://localhost:8080/teste/rest/api/v1/products?filter=code eq '000001' |
http://localhost:8080/teste/rest/api/v1/products?order=description |
http://localhost:8080/teste/rest/api/v1/products?fields=code,description |
A partir da lib 20220322 é possível utilizar os filtros toupper e tolower: filter=toupper(description) eq 'XISTO' filter=tolower(description) eq 'xis' A partir da lib 20220502 o JSON de retorno do GET com listagem, além de possuir a propriedade hasNext indicando que ainda existem registros a serem retornados, contará também com a propriedade remainingRecords, que retornará quantos registros ainda existem para retorno, facilitando assim por exemplo o cálculo da quantidade de páginas existentes. |
A classe não dá suporte ao campos memo que utilizam da SYP. |