How to parse std::list to json::value in casablanca? - c++

I'm trying to parse std::list to json::value with casablanca1.2.0 with Visual Studio 2012 and send JSON request with REST service(POST) from C++ application to Java Application.
REST service requires a request DTO like this.
// java
public class MyProfile {
private String name;
private List<String> favoriteFood;
...
}
So I tried to write C++ code, but I couldn't find how to convert std::list to json::value.
// C++
std::wstring name = "AAA";
std::list<std::wstring> favoriteFood = ...;
json::value requestData;
requestData[L"name"] = json::value::string(name);
std::vector<json::value::string> vvv;
for (auto itr = favoriteFood.begin(); itr != favoriteFood.end(); ++itr) {
vvv.push_back(json::value::string(*itr));
}
requestData[L"favoriteFood"] = json::value::array(vvv); // compile error occurs
I'm totally new to Casablanca and JSON, so I can't find any solution.
Any help would be very nice!!!

Related

Textract Form Analysis, Java SDK 1.x

I'm looking to extract form data utilizing textract. I've tested with a PDF in the demo and results are great. Results using the SDK however are far from optimal, actually, completely inaccurate. If I use StartDocumentAnalysisRequest/StartDocumentAnalysisResult (asynchronous), I only get 1 block returned of type PAGE, never KEY_VALUE_SET. If I convert my PDF to an image and use the synchronous methods, I do get KEY_VALUE_SET back but results are completely inaccurate.
Does anyone know how I can utilize the asynchronous analysis functionality to retrieve form values as the documentation indicates?
Sample Code below:
StartDocumentAnalysisResult startDocumentAnalysisResult = amazonTextract.startDocumentAnalysis(req);
String startJobId = startDocumentAnalysisResult.getJobId();
GetDocumentAnalysisResult documentAnalysisResult = null;
String jobStatus = "IN_PROGRESS";
while (jobStatus.equals("IN_PROGRESS")) {
try {
TimeUnit.SECONDS.sleep(10);
GetDocumentAnalysisRequest documentAnalysisRequest = new GetDocumentAnalysisRequest()
.withJobId(startJobId)
.withMaxResults(1);
documentAnalysisResult = amazonTextract.getDocumentAnalysis(documentAnalysisRequest);
jobStatus = documentAnalysisResult.getJobStatus();
} catch (Exception e) {
logger.error(e);
}
}
if (!jobStatus.equals("IN_PROGRESS")) {
List<Block> blocks = documentAnalysisResult.getBlocks();
logger.error("block list size " + blocks.size());
Map<String, Map<String, Block>> keyValueBlockMap = new HashMap<>();
Map<String, Block> keyMap = new HashMap<>();
Map<String, Block> valueMap = new HashMap<>();
Map<String, Block> blockMap = new HashMap<>();
for (Block block : blocks) {
logger.error("Block Type:" + block.getBlockType());
String blockId = block.getId();
blockMap.put(blockId, block);
if (block.getBlockType().equals("KEY_VALUE_SET")) {
if (block.getEntityTypes().contains("KEY")) {
keyMap.put(blockId, block);
} else {
valueMap.put(blockId, block);
}
}
}
keyValueBlockMap.put("keyMap", keyMap);
keyValueBlockMap.put("valueMap", valueMap);
keyValueBlockMap.put("blockMap", blockMap);
Map<String, String> keyValueRelationShip = getKeyValueRelationShip(keyValueBlockMap);
for (String key : keyValueRelationShip.keySet()) {
logger.error("Key: " + key);
logger.error("Value: " + keyValueRelationShip.get(key));
}
}
Synchronous path which results in completely horrible results:
AnalyzeDocumentRequest request = new AnalyzeDocumentRequest() .withFeatureTypes(FeatureType.FORMS) .withDocument(new Document(). withS3Object(new com.amazonaws.services.textract.model.S3Object() .withName(objectName) .withBucket(awsHelper.getS3BucketName())));
AnalyzeDocumentResult result = amazonTextract.analyzeDocument(request);
You are not using the recommended version for the AWS SDK for Java. You are using a old version and not the recommended one.
I have tested the AWS SDK for Java V2 and I am able to get lines and text that lines up with the AWS Management Console.
You can find textTract V2 examples in the repo linked above.
I am able to get to lines and the corresponding text by using software.amazon.awssdk.services.textract.TextractClient.
For example when i debug through the code using the same PNG as I used in the console, i get the proper result.

BaseX XML database in C++ encoding issue

I work with Base X and try to integrate a XML database with c++ on Windows 7. I use the BaseXclient API from https://github.com/JohnLeM/BasexCPPAPI/
it contains the pugixml parser and uses the boost lib. I got it to work but I have issues with the encoding. The xml dokuments in my database are utf-8 and contain some letters and symbols that are not displayed correctly on console output(like ä and °).
I set the console code page with chcp 65001.
I changed the locale with std::setlocale(LC_ALL, ""); in c++ and when I cout these letters and symbols directly in my Programm and not from the database they are displayed correctly. The database output also changed but is still wrong.
I also set the pugi parser with pugi::xml_encoding::encoding_utf8; but the database output is not affected. here is a code example from the string list interface:
virtual ~my_string_list_interface() {};
my_string_list_interface(const std::string& DBHOST, const std::string& DBPORT, const std::string& DBUSER,const std::string& DBPASSWD) : base_type(DBHOST,DBPORT,DBUSER,DBPASSWD) {};
virtual my_string_list get(string query,int stage){
my_string_list my_string_list_;
pugi::xml_encoding::encoding_auto;
pugi::xml_parse_result parse_;
pugi::xml_document doc;
string results = session().execute("XQUERY "+query);
parse_ = doc.load(results.c_str());
pugi::xpath_node_set is = doc.select_nodes("/record/mid");
The API uses boost streambuf to get the data. The code from boost streambuf looks like that:
std::string read_streambuffer(){return read_streambuffer(response_);};
std::string read_streambuffer(boost::asio::streambuf & response)
{
std::string results;
boost::system::error_code error;
boost::asio::streambuf::const_buffers_type bufs = response.data();
std::size_t size(0);
std::string line;
auto ptr_b = boost::asio::buffers_begin(bufs);
for(; ptr_b != boost::asio::buffers_end(bufs); ++ptr_b, ++ size)
{if (*ptr_b != 0) {line.push_back(*ptr_b);} else if (size > 1) break; };
response.consume(size);
return line;
};
Is there a way to specify the encoding for the buffer stream or string? I use a string list for the database output. should I use wstring or is there something i missed?
Thanks!

C++ REST (Casablanca) - Failure while reading JSON

I was trying my hands with C++ REST APIs
I wrote to json using below way.
json::value resp;
std::vector<Portfolio> portfolio;
// Populate portfolio
this->PortfolioList(usrStr, pwdStr, portfolio);
std::vector<Portfolio>::iterator it;
for (it = portfolio.begin(); it != portfolio.end(); it++)
{
char costBuff[40]; _itoa_s(it->GetTotalCost(), costBuff, 10);
char qtyBuff[40]; _itoa_s(it->GetQuantity(), qtyBuff, 10);
json::value portfolioEntry;
portfolioEntry[U("username")] = json::value::string(utility::conversions::to_string_t(it->GetUserName()));
portfolioEntry[U("stockCode")] = json::value::string(utility::conversions::to_string_t(it->GetStockCode()));
portfolioEntry[U("quantity")] = json::value::string(utility::conversions::to_string_t(qtyBuff));
portfolioEntry[U("totalcost")] = json::value::string(utility::conversions::to_string_t(costBuff));
resp[utility::conversions::to_string_t(it->GetStockCode())] = portfolioEntry;
}
For this I got output as below
{
"11002":{"quantity":11002,"totalcost":"272","username":"arunavk"},
"11003":{"quantity":11003,"totalcost":"18700","username":"arunavk"},
"11004":{"quantity":11004,"totalcost":"760","username":"arunavk"},
"11005":{"quantity":11005,"totalcost":"32","username":"arunavk"}
}
Now, on the receiving end, I tried to read it as below
for (int i = 0; i < size; i++)
{
table->elementAt(i, 0)->addWidget(new Wt::WText(this->response[i][0].as_string()));
table->elementAt(i, 1)->addWidget(new Wt::WText(this->response[i][1].as_string()));
table->elementAt(i, 2)->addWidget(new Wt::WText(this->response[i][2].as_string()));
table->elementAt(i, 3)->addWidget(new Wt::WText(this->response[i][3].as_string()));
}
But it fails. What am I missing ?
Pardon me, I am new to this REST and Casablanca and JSON
From JSON point of view the following
{
"11002":{"quantity":11002,"totalcost":"272","username":"arunavk"},
"11003":{"quantity":11003,"totalcost":"18700","username":"arunavk"},
"11004":{"quantity":11004,"totalcost":"760","username":"arunavk"},
"11005":{"quantity":11005,"totalcost":"32","username":"arunavk"}
}
is java script object with properties "11002", ... "11005", is not array. So if you want to get value of property you have to use property name:
this->response["11002"]["quantity"]
because when you use integer index the json::value::operator [] supposes that you want to access the array element. Here is details https://microsoft.github.io/cpprestsdk/classweb_1_1json_1_1value.html#a56c751a1c22d14b85b7f41a724100e22
UPDATED
If you do not know properties of the recieved object, you can call the value::as_object method (https://microsoft.github.io/cpprestsdk/classweb_1_1json_1_1value.html#a732030bdee11c2f054299a0fb148df0e) to get JSON object and after that you can use specilized interface to iterate through the fields with begin and end iterators: https://microsoft.github.io/cpprestsdk/classweb_1_1json_1_1object.html#details

Dynamic XML code generation in C++

I would like to transform some C++ objects of classes of my own into XML code. I guess there are several libraries which provide C++ to XML-mapping, but I would like to keep the library overhead simple and craft something of my own.
What would be an appropriate approach to generate XML building? In Java there are annotations which could be use to dynamaically generate the XML. Maybe the template mechanism?
I am using TinyXML so far. I really enjoy using it.
Here is an example, which I would like to be generated:
std::string XMLBuilder::buildThreadInformation(vector<threadinfo> threadinfos) {
TiXmlDocument document;
TiXmlDeclaration *declaration = new TiXmlDeclaration("1.0", "", "");
TiXmlElement *messageWrapElement = new TiXmlElement("message");
TiXmlElement *threadsElement = new TiXmlElement("threads");
messageWrapElement->LinkEndChild(threadsElement);
std::string numberString;
for (vector<threadinfo>::const_iterator it = threadinfos.begin(); it
!= threadinfos.end(); ++it) {
TiXmlElement *threadElement = new TiXmlElement("thread");
threadsElement->LinkEndChild(threadElement);
TiXmlElement *threadNumberElement = new TiXmlElement("number");
threadElement->LinkEndChild(threadNumberElement);
numberString = boost::lexical_cast<std::string>((*it).thread_number);
TiXmlText *threadNumber = new TiXmlText(numberString.c_str());
threadNumberElement->LinkEndChild(threadNumber);
TiXmlElement *threadNameElement = new TiXmlElement("name");
threadElement->LinkEndChild(threadNameElement);
TiXmlText *threadName = new TiXmlText((*it).name.c_str());
threadNameElement->LinkEndChild(threadName);
}
document.LinkEndChild(declaration);
document.LinkEndChild(messageWrapElement);
TiXmlPrinter printer;
document.Accept(&printer);
std::string result = printer.CStr();
return result;
}
The class threadinfo would consist of int number and std::string name.
RapidXML is also pretty easy to use and can create dynamic xml for you.

Custom webservice in Umbraco 4.5 giving odd error

We've created a custom webservice in Umbraco to add (async) files and upload them. After upload the service is called with node and file-information to add a new node to the content tree.
At first our main problem was that the service was running outside of the Umbraco context, giving strange errors with get_currentuser.
Now, we inherit the umbraco BaseWebService from the umbraco.webservices dll and we've set all acces information in the settings file; we authenticatie before doing anything else using (correct and ugly-hardcoded) administrator.
When we now execute the webservice (from the browser or anything else) we get:
at umbraco.DataLayer.SqlHelper`1.ExecuteReader(String commandText, IParameter[] parameters)
at umbraco.cms.businesslogic.CMSNode.setupNode()
at umbraco.cms.businesslogic.web.Document.setupNode()
at umbraco.cms.businesslogic.CMSNode..ctor(Int32 Id)
at umbraco.cms.businesslogic.Content..ctor(Int32 id)
at umbraco.cms.businesslogic.web.Document..ctor(Int32 id)
at FileUpload.AddDocument(String ProjectID, String NodeID, String FileName)*
Where AddDocument is our method. The node (filename w/o extension) does not exist in the tree (not anywhere, it's a new filename/node). We've cleared the recycle bin, so it's not in there either.
Are we missing something vital, does anyone has a solution?
Below is the source for the webservice;
using umbraco.cms.businesslogic.web;
using umbraco.BusinessLogic;
using umbraco.presentation.nodeFactory;
using umbraco.cms.businesslogic.member;
using umbraco.cms;
/// <summary>
/// Summary description for FileUpload
/// </summary>
[WebService(Namespace = "http://umbraco.org/webservices/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class FileUpload : umbraco.webservices.BaseWebService //System.Web.Services.WebService
{
private string GetMimeType(string fileName)
{
string mimeType = "application/unknown";
string ext = System.IO.Path.GetExtension(fileName).ToLower();
Microsoft.Win32.RegistryKey regKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(ext);
if (regKey != null && regKey.GetValue("Content Type") != null)
mimeType = regKey.GetValue("Content Type").ToString();
return mimeType;
}
[WebMethod]
public string HelloWorld() {
return "Hello World";
}
[WebMethod]
public void AddDocument(string ProjectID, string NodeID, string FileName)
{
Authenticate("***", "***");
string MimeType = GetMimeType(FileName); //"application/unknown";
// Create node
int nodeId = 1197;
string fileName = System.IO.Path.GetFileNameWithoutExtension(#"*****\Upload\" + FileName);
string secGroups = "";
//EDIT DUE TO COMMENT: Behavior remains the same though
Document node = umbraco.cms.businesslogic.web.Document.MakeNew(fileName.Replace(".", ""), new DocumentType(1049), umbraco.BusinessLogic.User.GetUser(0), nodeId);
secGroups = "Intern";
StreamWriter sw = null;
try
{
//EXCEPTION IS THROWN SOMEWHERE HERE
Document doc = NodeLevel.CreateNode(fileName, "Bestand", nodeId);
doc.getProperty("bestandsNaam").Value = fileName;
byte[] buffer = System.IO.File.ReadAllBytes(#"****\Upload\" + FileName);
int projectId = 0;
int tempid = nodeId;
//EXCEPTION IS THROWN TO THIS POINT (SEE BELOW)
try
{
Access.ProtectPage(false, doc.Id, 1103, 1103);
Access.AddMembershipRoleToDocument(doc.Id, secGroups);
}
catch (Exception ex)
{
// write to file
}
try
{
doc.Publish(umbraco.BusinessLogic.User.GetUser(0));
umbraco.library.UpdateDocumentCache(doc.Id);
umbraco.content.Instance.RefreshContentFromDatabaseAsync();
}
catch (Exception ex)
{
// write to file
}
System.IO.File.Delete(FileName);
}
catch (Exception ex)
{
// THIS EXCEPTION IS CAUGHT!!
}
}
public override umbraco.webservices.BaseWebService.Services Service
{
get { return umbraco.webservices.BaseWebService.Services.DocumentService; }
}
}
If anyone has a solution, pointer, hint or whatever; help is appreciated!!
TIA,
riffnl
We've rewritten the whole procedure (dumped all code and restart) and we've got it working now.
I think we've been messing around with the old code so much in trying to get it to work we were missing some key issues, because it functions.
Thanks for thinking along anyway!