Utilizado a class FWAdapterBaseV2, não sei dizer, eu fiz um API que retorna alguns dados no caso do formatação da data eu faço no momento de preencher o valor do campo JSON.
Segue um exemplo resumido da class com GET,
WSRESTFUL LwCroMnt DESCRIPTION "Rest para manipula e visualizar de dados do cronograma de manutenção em geral"
WSDATA id AS STRING OPTIONAL
WSDATA ano AS STRING OPTIONAL
WSDATA page AS INTEGER OPTIONAL
WSDATA pageSize AS INTEGER OPTIONAL
WSDATA searchKey AS STRING OPTIONAL
WSDATA openOS as String Optional //indiciar se irá lista OS aberta ou já em atendimento.
WSMETHOD GET listOSCorr DESCRIPTION "Obtem lista de O.S. corretivas" WSSYNTAX "LwCroMnt/listOSCorr" PATH "/LwCroMnt/listOSCorr"
END WSRESTFUL
WSMETHOD GET listOSCorr WSRECEIVE openOS, page, pageSize WSSERVICE LwCroMnt
lOCAL lRet := .t.
Local oStruZAK := NIL
Local oJSOS := NIL
Local aListCpOS := {}
Local cJsonOS := ''
Local cAliasStruc := "TMPSX3"
lOCAL aCampoZAK := {}
Local lFilAbertas := .T.
Local oJOS := JsonObject():New()
Default self:openOS := ''
Default self:page := 1
Default self:pageSize := 10
oJSOS := JsonObject():New()
::SetContentType("application/json")
if(!Empty(self:openOS ))
lFilAbertas := .F.
endif
BeginSql Alias cAliasStruc
SELECT X3_CAMPO, X3_TIPO, X3_TAMANHO, X3_DECIMAL, X3_TITULO, X3_DESCRIC
FROM SX3010 WHERE X3_ARQUIVO = 'ZAK' AND D_E_L_E_T_ != '*' and X3_CONTEXT = 'R'
AND X3_USADO = 'x x x x x x x x x x x x x x x x '
EndSql
If (cAliasStruc)->(!Eof())
while (cAliasStruc)->(!Eof())
AADD(aCampoZAK, {(cAliasStruc)->&("X3_CAMPO"),;
(cAliasStruc)->&("X3_TIPO"),;
(cAliasStruc)->&("X3_TAMANHO"),;
(cAliasStruc)->&("X3_DECIMAL"),;
(cAliasStruc)->&("X3_TITULO"),;
(cAliasStruc)->&("X3_DESCRIC")})
dbSelectArea(cAliasStruc)
(cAliasStruc)->(dbSkip())
endDo
EndIf
(cAliasStruc)->(DbCloseArea())
oStruZAK := aCampoZAK
cAlias := GetNextAlias()
if(lFilAbertas)
cWhere := "%ZAK_DTINI = ' '%"
else
cWhere := "%ZAK_DTINI != ' '%"
endif
BeginSql Alias cAlias
SELECT
ZAK.*,
TRIM(UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(ZAK_DEFEIT,2000))) as TMP_DEFEIT,
TRIM(UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(ZAK_MOTIVO,2000))) as TMP_MOTIVO,
SUBSTR(SRA.RA_NOME,1,15) NOMESOL,
SUBSTR(SRA2.RA_NOME,1,15) NOMERESP
FROM %table:ZAK% ZAK
INNER JOIN %table:SRA% SRA ON ZAK.ZAK_SOLICI = SRA.RA_MAT
LEFT JOIN %table:SRA% SRA2 ON ZAK.ZAK_RESPON = SRA2.RA_MAT
WHERE ZAK_TIPO = 'C' AND ZAK_MO = 'M' AND (ZAK_STATUS != 'F' AND ZAK_STATUS != 'X') AND ZAK_AGENDA = 'N'
AND ZAK.D_E_L_E_T_ = ' '
AND %Exp:cWhere%
ORDER BY ZAK_PRIORI DESC, ZAK_DATA, ZAK_HORA
EndSql
If ( cAlias )->( ! Eof() )
//-------------------------------------------------------------------
// Identifica a quantidade de registro no alias temporário
//-------------------------------------------------------------------
COUNT TO nRecord
//-------------------------------------------------------------------
// nStart -> primeiro registro da pagina
// nReg -> numero de registros do inicio da pagina ao fim do arquivo
//-------------------------------------------------------------------
If self:page > 1
nStart := ( ( self:page - 1 ) * self:pageSize ) + 1
nReg := nRecord - nStart + 1
Else
nReg := nRecord
EndIf
//-------------------------------------------------------------------
// Posiciona no primeiro registro.
//-------------------------------------------------------------------
( cAlias )->( DBGoTop() )
//-------------------------------------------------------------------
// Valida a exitencia de mais paginas
//-------------------------------------------------------------------
If nReg > self:pageSize
oJOS['hasNext'] := .T.
Else
oJOS['hasNext'] := .F.
EndIf
Else
//-------------------------------------------------------------------
// Nao encontrou registros
//-------------------------------------------------------------------
oJOS['hasNext'] := .F.
EndIf
aOSJS := {}
If (cAlias)->(!Eof())
while (cAlias)->(!Eof())
aListCpOS := JsonObject():New()
aListCpOS['ZAK_CODIGO'] := (cAlias)->&("ZAK_CODIGO")
aListCpOS['ZAK_DATA'] := DtoC(StoD((cAlias)->&("ZAK_DATA")))
aListCpOS['ZAK_HORA'] := (cAlias)->&("ZAK_HORA")
aListCpOS['NOMESOL'] := (cAlias)->&("NOMESOL")
aListCpOS['NOMERESP'] := (cAlias)->&("NOMERESP")
aListCpOS['TMP_DEFEIT'] := allTrim((cAlias)->&("TMP_DEFEIT"))
aListCpOS['TMP_MOTIVO'] := allTrim((cAlias)->&("TMP_MOTIVO"))
aListCpOS['ZAK_PRIORI'] := allTrim((cAlias)->&("ZAK_PRIORI"))
aListCpOS['ZAK_DTINI'] := DtoC(StoD((cAlias)->&("ZAK_DTINI")))
aadd(aOSJS,aListCpOS)
aListCpOS := NIL
dbSelectArea(cAlias)
(cAlias)->(dbSkip())
endDo
Else
EndIf
(cAlias)->(DbCloseArea())
oJOS['items'] := aOSJS
//-------------------------------------------------------------------
// Serializa objeto Json
//-------------------------------------------------------------------
cJsonOS:= EncodeUTF8(oJOS:toJson())
//-------------------------------------------------------------------
// Elimina objeto da memoria
//-------------------------------------------------------------------
FreeObj(oJOS)
Self:SetResponse( cJsonOS ) //--enviar JSON(string) na requisição da resposta
Return lRet