2010-05-18 31 views
48

Tôi đang cố gắng tuần tự hóa bằng cách sử dụng cây thuộc tính boost write_json, nó tiết kiệm mọi thứ dưới dạng chuỗi, không phải dữ liệu sai, nhưng tôi cần phải sử dụng chúng một cách rõ ràng mọi lúc và tôi muốn sử dụng chúng ở một nơi khác. (Như trong python hoặc khác C++ json (không tăng) thư viện)Tại sao tăng property property write_json lưu mọi thứ dưới dạng chuỗi? Có thể thay đổi điều đó không?

đây là một số mẫu mã và những gì tôi nhận được tùy thuộc vào ngôn ngữ:

boost::property_tree::ptree root, arr, elem1, elem2; 
elem1.put<int>("key0", 0); 
elem1.put<bool>("key1", true); 
elem2.put<float>("key2", 2.2f); 
elem2.put<double>("key3", 3.3); 
arr.push_back(std::make_pair("", elem1)); 
arr.push_back(std::make_pair("", elem2)); 
root.put_child("path1.path2", arr); 

std::stringstream ss; 
write_json(ss, root); 
std::string my_string_to_send_somewhare_else = ss.str(); 

my_string_to_send_somewhere_else là sth. như thế này:

{ 
    "path1" : 
    { 
     "path2" : 
     [ 
      { 
       "key0" : "0", 
       "key1" : "true" 
      }, 
      { 
       "key2" : "2.2", 
       "key3" : "3.3" 
      } 
     ] 
    } 
} 

Liệu có cách nào để cứu họ như các giá trị, như: "key1" : true hoặc "key2" : 2.2?

Trả lời

2

Từ JSON được xuất, rõ ràng là serializer nối tiếp mọi thứ với chuỗi bằng cách sử dụng phương thức .toString() - nghĩa là không biết loại của mỗi thành viên và bao quanh mọi thứ trong "".

Xem Creating JSON arrays in Boost using Property Trees để biết thêm về vấn đề này.

32

Ok, tôi đã giải quyết nó như thế này, (tất nhiên nó sẽ không dành cho tất cả mọi người, vì nó là một chút của một hack, mà cần thêm công việc).


Tôi đã viết riêng write_json chức năng của tôi (chỉ cần sao chép các tập tin, json_parser.hppjson_parser_write.hpp để dự án của tôi) và sửa đổi những dòng sau trong json_parser_write.hpp:

  1. nhận xét dòng 37 - thoát báo giá ' "'
  2. thay đổi dòng 76 - vì vậy mà nó không thêm dấu ngoặc kép nữa: stream << Ch('"') << data << Ch('"'); ==> stream << data;

Sau đó, giá trị này sẽ được lưu đúng ngoại trừ cho các chuỗi, vì vậy tôi đã viết dịch tùy chỉnh cho nó:

template <typename T> 
struct my_id_translator 
{ 
    typedef T internal_type; 
    typedef T external_type; 

    boost::optional<T> get_value(const T &v) { return v.substr(1, v.size() - 2) ; } 
    boost::optional<T> put_value(const T &v) { return '"' + v +'"'; } 
}; 

và chuỗi đơn giản là lưu sử dụng:

elem2.put<std::string>("key2", "asdf", my_id_translator<std::string>()); 

hoàn thành chương trình:

#include <iostream> 
#include <string> 
#include <sstream> 

#include <boost/property_tree/ptree.hpp> 

#include "property_tree/json_parser.hpp" // copied the headers 

template <typename T> 

struct my_id_translator 
{ 
    typedef T internal_type; 
    typedef T external_type; 

    boost::optional<T> get_value(const T &v) { return v.substr(1, v.size() - 2) ; } 
    boost::optional<T> put_value(const T &v) { return '"' + v +'"'; } 
}; 

int main(int, char *[]) 
{ 
    using namespace std; 
    using boost::property_tree::ptree; 
    using boost::property_tree::basic_ptree; 
    try 
    { 
     ptree root, arr,elem2; 
     basic_ptree<std::string, std::string> elem1; 
     elem1.put<int>("int", 10); 
     elem1.put<bool>("bool", true); 
     elem2.put<double>("double", 2.2); 
     elem2.put<std::string>("string", "some string", my_id_translator<std::string>()); 

     arr.push_back(std::make_pair("", elem1)); 
     arr.push_back(std::make_pair("", elem2)); 
     root.put_child("path1.path2", arr); 

     std::stringstream ss; 
     write_json(ss, root); 
     std::string my_string_to_send_somewhere_else = ss.str(); 

     cout << my_string_to_send_somewhere_else << endl; 

    } 
    catch (std::exception & e) 
    { 
     cout << e.what(); 
    } 
    return 0; 
} 

kết quả :)

{ 
    "path1": 
    { 
     "path2": 
     [ 
      { 
       "int": 10, 
       "bool": true 
      }, 
      { 
       "double": 2.2, 
       "string": "some string" 
      } 
     ] 
    } 
} 
+4

+ 1 hữu ích để biết không có giải pháp sạch ngay bây giờ, và rằng một kludge là cần thiết –

+1

Nếu báo giá kép không được thoát sau đó bạn có thể chạy với một vấn đề nếu báo giá này xảy ra được trong chuỗi của bạn. – Bogolt

+0

ở cuối nó làm việc để viết và đọc cũng. Hay đây là chỉ ghi? – alfC

3

Như chúng ta đã gõ basic_ptree < std :: string, std :: string > ptree; trong các thư viện boost, boost sẽ luôn luôn tuần tự hóa từng giá trị dưới dạng chuỗi và phân tích tất cả các giá trị thành một chuỗi tương đương.

3

Giải pháp đơn giản và sạch nhất mà tôi có thể đưa ra là tạo JSON với trình giữ chỗ và trong chuỗi kết thúc thay thế bằng giá trị thực tế bỏ qua các dấu ngoặc kép bổ sung.

static string buildGetOrdersCommand() { 
    ptree root; 
    ptree element; 
    element.put<string>("pendingOnly", ":pendingOnly"); 
    element.put<string>("someIntValue", ":someIntValue"); 

    root.put("command", "getOrders"); 
    root.put_child("arguments", element); 

    std::ostringstream buf; 
    write_json(buf, root, false); 
    buf << std::endl; 

    string json = buf.str(); 
    replace(json, ":pendingOnly", "true"); 
    replace(json, ":someIntValue", std::to_string(15)); 

    return json; 
} 

static void replace(string& json, const string& placeholder, const string& value) { 
    boost::replace_all<string>(json, "\"" + placeholder + "\"", value); 
} 

Và kết quả là

{ "lệnh": "getOrders", "lập luận": { "pendingOnly": đúng, "someIntValue": 15}}

Các vấn đề liên quan