Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Capture data from a formated text 2

Status
Not open for further replies.

SitesMasstec

Programmer
Sep 26, 2010
508
Brasil
Hello colleagues!

I have, at last, been using CURSOR, thank you.

In the small program bellow I send a request to an API provider:

Code:
xmlHttp = CREATEOBJECT("MSXML2.ServerXMLHTTP")

* xmlHttp.open("GET", "[URL unfurl="true"]https://api.postmon.com.br/v1/cep/13041-620",[/URL] null)
* Substitituído pelas 3 linhas abaixo:
myCEP="33236-434"  && Value (in the real program it will be a variable)
CEPparaAPI="[URL unfurl="true"]https://api.postmon.com.br/v1/cep/"+myCEP[/URL]
xmlHttp.open("GET", CEPparaAPI, null)

xmlHttp.setRequestHeader("Content-Type", "text/xml")
xmlHttp.send("")
result = xmlHttp.responseText
? result

The result is:

RESULTADO_ku8pg4.jpg


This is Ok.

Then, I created a Cursor to populate with data read from API, that is, I want to "consume" the data:

Code:
CREATE CURSOR my_Endereco;
(   my_bairro c(22),;
    my_cidade c(20),;
    my_logradouro c(34),;
    my_estado c(2) )


    my_bairro = STREXTRACT( result, ["bairro": ], [,] )
    my_cidade = STREXTRACT( result, ["cidade": ], [,] )

*   etc etc

? my_bairro 
? my_cidade

* Comands to populate the Cursor will be here

But I have not got any result to my_bairro and my_cidade ...
It seems something wrong with STREXTRACT parameters I had informed.


Thank you,
SitesMasstec
 
VFP has no JSON functionality, a bit of XML, but the way atlopes was using XML was using the functionality built into MSXML2.ServerXMLHTTP.6.0 and the MSXML2.DOMDocument60 classes - and that's just what you get as ResponseXML object, if you request an XML result.

So this doesn't even depend on VFP having language elements coping with XML or JSON.

The nfJSON library from atlopes also is good for using JSON and West Wind also is providing both XML and JSON. What you want to do will depend on what you can use. As you see yourself, JSON is having more popularity by now in web services, you'll sometimes be able to choose, as here with the format=xml parameter used or not used. In other cases you might only get JSON or only XML, you never know.

In any case both JSON and XML and even other formats are all essentially text-based and can be handled in many ways.

I don't need to repeat the points atlopes made already about what situations to think about and handle.
Besides West Wind, there are other libraries available like Carlos Alloattis' or vfpconnection.fll from Craig Boyd, currently only broken links for the latter, though.

In the end MSXML2.ServerXMLHTTP or MSXML2.XMLHTTP are already good options for HTTP and XML. There is no inbuilt similar functionality for JSON in these classes, though, as JSON is just native for Javascript and that's mostly used as web development language, so there is no need to offer something like the Selectnodes for JSON. The advantage JSON has to XML is that it's lightweight and better human readable, but it also depends on what kind of tools you use, XML can also be displayed user friendlier as a tree of informations, for example, in a browser and, of course, you'll usually extract what you need from the JSON and XML just like you did and use that data extracted from XML or JSON.

Chriss
 
Chriss, I understand and so, I need to study how to process both JSON and XML data, but with preference to JSON.

As I am using web services for the first time, I understood through your and atlopes's postas that I need to study libraries/classes to extract data from APIs.

But before that, I am locked for not solved the problem of UTF-8 characters code, even if typed directly in the browser:
(JSON result)
AcentuacaoJSON_xbvn59.jpg




Thank you,
SitesMasstec
 
Well, that is encoding JS would display right. Since it is just JSON even a browser will show you just the "source code", not the evaluation of this as the Unicode codepoints 00e9 and 00e1 (hexadecimal).

But indeed on a JS console these Unicode encoded characters display correctly:

unicode_ltnz4z.jpg


There's nothing inbuilt for this JS string encoding called "escape sequence". On first glimpse, Windows also only offers API functions for URL encoded characters in the format %hh, but not \uhhhh (where h stands for hexadecimal digit). But you can extract the hexadecimal code for the Unicode characters and convert them to ANSI with
Code:
? Strconv(0he100,6) && á
? Strconv(0he900,6) && é

Just notice this is in reverse byte order: \u00e9 vs 0he900. So any occurrence of \u followed by 4 digits can be converted. At least you can try. You will get a question mark for any Unicode character not covered by your current Ansi codepage of VFP, but surely letters like this and many more will be available.

Chriss
 
Hello colleagues!

I want to thank you all. At last, I am beginning to use nfJSON functions, without "reinvent the wheel", as Greg told earlier. I got the expected result:
FormAPI2_epnoa2.jpg


Code:
myCEP=thisform.txtCccep.Value


IF SUBSTR(myCEP,1,1)<>" "
	xmlHttp = CREATEOBJECT("MSXML2.ServerXMLHTTP")

	CEPparaAPI="[URL unfurl="true"]https://api.postmon.com.br/v1/cep/"+myCEP[/URL]
	xmlHttp.open("GET", CEPparaAPI, null)

	xmlHttp.setRequestHeader("Accept", "application/json") 

	xmlHttp.send()     

	Resposta = xmlHttp.responseText

	vfpobj = nfJsonRead(Resposta)

*   Leitura das variaveis 
	my_logradouro = vfpobj.logradouro
	my_bairro = vfpobj.bairro
	my_cidade = vfpobj.cidade
	my_estado = vfpobj.estado

	thisform.txtResposta.Value = Resposta

	thisform.txtCende.Value = my_logradouro
	thisform.txtCbair.Value = my_bairro
	thisform.txtCcida.Value = my_cidade
	thisform.txtCesta.Value = my_estado
ENDIF

Thank you,
SitesMasstec
 
Looks good. nfJSON includes converting unicode escape sequences, using STRCONV(), too. So, this is a good example of how using a library is having an advantage over doing things from scratch. At first glimpse you have to dig into the howto and getting started with the library, but if it's matured it has such features already built into it. You could get away with a few STREXTRACT, if there was no unicode escape sequences for letters that don't really require to escape them.

What I am missing in your example is adding the error handling about the result state.

I wonder why you do IF SUBSTR(myCEP,1,1)<>" ", and not simpler IF NOT myCEP=="" or IF NOT EMPTY(myCEP). You could also do myCEP=ALLTRIM(thisform.txtCccep.Value) to remove any leading or trailing whitepace entered by the user erroneously, but likely unintended.

With JSON there is one more simple way to interpret it, by running it as Javascript. It comes with a few caveats, though...
Code:
xmlHttp = Createobject("MSXML2.ServerXMLHTTP")

CEPparaAPI="[URL unfurl="true"]https://api.postmon.com.br/v1/cep/13178-100"[/URL]
xmlHttp.Open("GET", CEPparaAPI,.F.)

* xmlHttp.setRequestHeader("Accept", "application/json") && not necessary
xmlHttp.Send()

If xmlHttp.status = 200 && ok
   Local lcJSON, loJS, loJSON
   lcJSON = xmlHttp.responseText
   If xmlHttp.getResponseHeader('Content-Type')=='application/json'

      loJS = Createobject("MSScriptControl.ScriptControl")
      loJS.Language="JavaScript"
      loJSON = loJS.Eval('('+lcJSON+')')
*!*	      ? lcJSON
*!*	      ? '--------------'

      ? loJSON.logradouro
      ? loJSON.bairro
      ? loJSON.cidade
      ? loJSON.estado

   Else
      ? 'Cannot handle (yet) content type '+xmlHttp.getResponseHeader('Content-Type')
      * handling of other  response content types
   Endif
Else
   * handling of other HTTP response states, 404 "not found", for example, or 503 "service not available" etc.
   ? 'Response Status:'+xmlHttp.statusText
Endif

The caveats of this code are that MSScriptControl.ScriptControl uses a very old JS engine. It's sufficient to evaluate JSON into an object and as you can see also captures the é letter correctly in doing so and converting the Javascript object to a VFP object. It has both the chance and the risk of executing further JS code embedded into the JSON. I don't think of this as a threat in the first place, because I'd trust api.postmon.com.br to only ever return JS code, if that's indeed needed or useful in the JSON evaluation. Anyway, I would recommend to stay with nfJSON, as it won't allow any malicious JS code to execute, the JS that would execute with the evaluation by the MSScriptControl.ScriptControl would instead just be extracted as a value. And if something is used in the JSON, that the old Javascript engine behind the script control object does not understand, chances are nfJSON will or you at least get an extracted value and could open a feature request in atlopes Github to add that JSON feature.

I commented the "Accept" header. In this service, s long as you don't add '?format=xml' to the URL, the response Content-Type will be application/json, no matter if you say that you will accept that content-type or not. Which means what I already said: You can't and won't enforce the result content type with an Accept header. It has no influence. Which can be seen by intentionally requesting the response for an unknown or wrong CEP: The response status then is 404 and the Content-Type sent back is HTML, a HTML page displaying the error to a user, if it would be shown in a browser. So no matter that you said you "only" accept JSON as a result content-type, the server still sends you the Mime type text/html and not application/json.

Another example you already could have realized and seen is if you set Accept to application/xml the service still sends back application/json, as it only reacts to the format parameter, if it's used in the URL of the request.

Any Accept header isn't forcing the server, it's just encouraging this response content type, but a server can even ignore it, it's not binding, it just can trigger content negotiation, but it's never forced. It won't even lead the server to not send back JSON when you say you only accept application/xml but don't send the format=xml parameter. It simply is ignored and not even in the overarching processing of HTPP requests by any web server on top of what the serverside script makes of the request, is it stopping a response that's not one of the accepted content types. So in simple terms, it's like saying you accept ketchup with your fries and still you get served fries with mayonnaise.

See and
In this service the only determining factor is the format URL parameter and the service defaults to JSON, if not explicitly asked to provide XML. In general, thinking of any API service or any webserver, accept is only helpful, if you know the server respects it and does respond differently with different Accept headers sent to it. It's not enough that a service can (obviously in this case) return both JSON and XML that this can then also be controlled by the Accept header. In this case, they decided server-side to only make the difference of what to return by the URL parameterization. Not by Accept header.

Chriss
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top