'Write JSON txt query to file in r

query<-'{
  "query": [
    {
      "code": "Region",
      "selection": {
        "filter": "item",
        "values": [
          "3010",
          "4020"          
        ]
      }
    },
    {
      "code": "Sex",
      "selection": {
        "filter": "item",
        "values": [
          "1",
          "2"
        ]
      }
 }
    
  ],
  "response": {
    "format": "json-stat2"
  }
}'

Now - how can I write the query string to file and retrieve it. So far I've tried writelines, save etc, but I retrieve multiple strings rather than one long string.



Solution 1:[1]

To answer a question in the title:

Yes, there IS a way to search a string.

To look for any single character (for example, decimal point), use find.

To look for any one of the list of characters (for example, digits) use find_first_of.

Solution 2:[2]

And to answer the question body, if you wish to know what "type" of thing a string contains you have two options:

  • try to convert it to that type (using istringstream and operator >>)
  • use a regular expression (or other pattern matching algorithm)

As already noted to you, this takes the effort on your part to clearly specify what uniquely constitutes each "type" of thing you wish to identify.

For example. In C++, 1 is an int, 1.0 is a double, etc.

Solution 3:[3]

you could do a rough check, find_first_not_of("01234567890.") to see if it looks like a number or not. Then do lexical_cast (or stringstream <<) and see if it succeeds. If not then assume string.

Probably should do 0123456789 (not .) to see if its an integer, then if the first_not_of is "." do a lexicalcast as float else treat it as character string

probably sniff at first char to see if '-'

Solution 4:[4]

It seems you want a parser that infers the type of the expression. This can be accomplished by trying different conversions and see if they succeed. Whenever they fail, jump to the next conversion. So a 1 would be a std::uint8_t, but a -1 would be a std::int8_t, a 1.0 would be a float while a 1e+40 would be a double and so forth.

Fortunately C++17 added a function that does close to what you want: std::from_chars.

#include <charconv>
#include <string>
#include <variant>
#include <optional>
#include <cstdint>

namespace {
  using Value = std::variant<
    long double, double, float,
    std::uint64_t, std::int64_t,
    std::uint32_t, std::int32_t,
    std::uint16_t, std::int16_t,
    std::uint8_t, std::int8_t,
    std::string // last resort if nothing works
  >;  

  template <typename T>
  std::optional<T> parse_as(char const* const begin, char const* const end) {
    if (begin == end) return std::nullopt;
    T value{};
    auto const [ptr, ec] = std::from_chars(begin,end,value);
    if (ec == std::errc::result_out_of_range || ec == std::errc::invalid_argument || ptr != end) {
      return std::nullopt;
    }
    return value;
  }

  Value parse(std::string const& str) {
    auto const b = str.data();
    auto const e = str.data() + str.size();
    if (auto const r = parse_as<std::uint8_t>(b,e)) return *r; 
    if (auto const r = parse_as<std::int8_t>(b,e)) return *r; 
    if (auto const r = parse_as<std::uint16_t>(b,e)) return *r; 
    if (auto const r = parse_as<std::int16_t>(b,e)) return *r; 
    if (auto const r = parse_as<std::uint32_t>(b,e)) return *r; 
    if (auto const r = parse_as<std::int32_t>(b,e)) return *r; 
    if (auto const r = parse_as<std::uint64_t>(b,e)) return *r; 
    if (auto const r = parse_as<std::int64_t>(b,e)) return *r; 
    if (auto const r = parse_as<float>(b,e)) return *r; 
    if (auto const r = parse_as<double>(b,e)) return *r; 
    if (auto const r = parse_as<long double>(b,e)) return *r;
    return str;
  }
}

Here is a small test that shows how this works:

#include <iostream>

// helper type
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };

void show(std::string const& str) {
  std::visit(overloaded {
    [](std::uint8_t const arg) {
        std::cout << int{arg} << "\tsize: " << sizeof(arg) << "\n";
    },
    [](std::int8_t const arg) {
        std::cout << int{arg} << "\tsize: " << sizeof(arg) << "\n";
    },
    [](auto const arg) {
        std::cout << arg << "\tsize: " << sizeof(arg) << "\n";
    }
    }, parse(str));
}

int main() {
  show("hello");
  show("64");
  show("7000");
  show("-7000");
  show("-127");
  show("1.0");
  show("1e+40");
  show("1e+400");
}

This will correctly print:

hello   size: 32
64      size: 1
7000    size: 2
-7000   size: 2
-127    size: 1
1       size: 4
1e+40   size: 8
1e+400  size: 16

Here is a live demo.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Vlad Feinstein
Solution 2 DĂșthomhas
Solution 3 pm100
Solution 4 bitmask