1

Here there, sorry if this question is not well-suited for this forum. I'm pretty new to programming and thought I'd get a better command of strings and files by creating this little project. What I'm trying to do is extract data from a JSON document. Eventually I'd store the data in an array I suppose and work with it later.

Basically, I'm wondering if there is a better way of going about this. The code seems kind of wordy and definitely not elegant. Again, sorry if this question is not a good one, but I figured there'd be no better way to learn than through a community like this.

#include <iostream>
#include <fstream>
#include <cstring>
#include <string>  //probably including more than necessary

using namespace std; //should be specifying items using scope resolution operator instead


int main(int argc, const char * argv[])
{

    ifstream sfile("JSONdatatest.txt");
    string line,temp;


    while(!sfile.eof()){

        getline(sfile, line);
        temp.append(line);  //creates string from file text, use of temp seems extraneous

    }
    sfile.close();


    cout << "Reading from the file.\n";
    size_t counter=0;
    size_t found=0;
    size_t datasize=0;

    while(found!=string::npos && found<1000*70){ //problem here, program was creating infinite loop
                                                 //initial 'solution' was to constrain found var
                                                 //but fixed with if statement

    found = temp.find("name: ",counter);
        if(found!=string::npos){ 

    found=found+7; //length of find variable "name: ", puts us to the point where data begins
    size_t ended=temp.find_first_of( "\"", found);

    size_t len=ended-found; //length of datum to extract


    string temp2(temp, found, len); //odd use of a second temp function, 
        cout << temp2 << endl;
        counter=ended+1;
        datasize++; //also problem with data size and counter, so many counters, can they 
                    //coordinate to have fewer?
    }

    }

    cout << datasize;


return 0}

Where I indicate an infinite loop is made, I fixed by adding the if statement in the while loop. My guess is because I add 7 to 'found' there is a chance it skips over npos and the loop continues. Adding the if statement fixed it, but made the code look clunky. There has to be a more elegant solution. Thanks in advance!

3
  • Is there a reason you're not using a JSON parser? Commented May 25, 2014 at 22:52
  • Could you use third party library's JSON parser? Casablanca project has one within it for example. Take a look. Commented May 25, 2014 at 23:20
  • Thanks for the comments. I've looked around and suppose I'll ultimately go for that, with its increased functionality. @WilliamAndrewMontgomery I was hoping to better my understanding of strings and files with this, probably not the best project idea though, haha. Commented May 26, 2014 at 0:34

1 Answer 1

5

I would recommend that you use a third-party to do all this stuff, which is pretty tough with raw tools. I actually did this kind of stuff recently so I can give you some help.

I would recommend you take a look at boost::property_tree . Here is the theory: A Json file is like a tree, you have a root, and many branches. The idea is to transform this JSON file into a boost::property_tree::ptree, so then you use easily the object ptree and not the file.

First, let's say we have this JSON file:

{
    "document": {
        "person": {
            "name": "JOHN",
            "age": 21
        },
        "code": "AX-GFD123"
     }

    "body" : "none"

}

Then in your code, be sure to include:

 #include "boost/property_tree/ptree.hpp"
 #include "boost/property_tree/json_parser.hpp"

Then here is the most interesting part:

 boost::property_tree::ptree root;

You create the ptree object named root.

boost::property_tree::read_json("/path_to_my_file/doc.json", root);

Then you tell what file to read, and where to store it (here in root). Be careful, you should use try / catch on this in case the file doesn't exist.

Then you will only use the root tree which is really easy to do. You have many functions (I invite you to see the boost documentation page).

You want to access the namefield. Right then do this:

std::string myname = root.get<std::string> ("document.person.name", "NOT FOUND");

The get function has the first parameter the path to get the attribute you want, the second is for default return if the path is incorrect or doesn't exist. the <std::string> is to show what type it must return.

Let's finish with another example. Let's say you want to check all your root nodes, that means every node which are on the top level.

  BOOST_FOREACH(const boost::property_tree::ptree::value_type& child, root.get_child(""))
  { cout << child.first << endl; }

This is a bit more complicated. I explain. You tell boost to look every child of the root with root.get_child("") , "" is used for root. Then, for every child found, (like a basic iterator), you will use const boost::property_tree::ptree::value_type& child.

So inside the foreach, you will use the child to access whatever you want. child.firstwill give you the name of the child node currently in use. In my example it will print first document, and then body.

I invite you to have a look at Boost documentation. It looks maybe hard at first, but it is really easy to use after that.

http://www.boost.org/doc/libs/1_41_0/doc/html/property_tree.html

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for this awesome response. It's probably time I get a bit more deep into the meat of it. This is a great starting point for working with JSON.
I'm glad this helps. Boost will seem a bit complicated at first, but no worries, read documentation, try little functions, and then you will get used to it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.