2013-06-10 23 views
13

Tôi hiện đang sử dụng Qt5.0 với thư viện QJson lõi để xử lý một số dữ liệu cho chương trình tôi đang phát triển.Làm thế nào để thay đổi giá trị QJsonObject trong phân cấp QJson mà không cần sử dụng bản sao?

Để thiết lập các cảnh cho câu hỏi này, tôi sẽ cung cấp cho bạn một số dữ liệu JSON minh họa vấn đề của tôi:

{ 
    "CLOCKS": [ 
     { 
      "ID": "clk", 
      "MAX": 2e+08, 
      "MIN": 1e+07, 
      "VALUE": "no_clock" 
     }, 
     { 
      "ID": "memclk", 
      "MAX": 2e+08, 
      "MIN": 1e+07, 
      "VALUE": "memclk" 
     } 
    ] 
} 

Ở đây chúng ta có một QJsonObject mẹ có chứa một chìa khóa duy nhất 'ĐỒNG HỒ'. Giá trị cho khóa này là QJsonArray của QJsonObjects chứa một số cặp khóa/giá trị chứa dữ liệu của tôi.

Nếu tôi muốn lấy QJsonObject với id 'CLK' Tôi hiện đang sử dụng mã như thế này:

// imagine m_data is my parent QJsonObject 
QJsonArray clocks = m_data["CLOCKS"].toArray(); 
foreach (const QJsonValue & value, clocks) { 
    QJsonObject obj = value.toObject(); 
    if (obj["ID"].toString() == "clk") { 
     return obj; 
    } 
} 

này hoạt động tốt và thư viện đã được tuyệt vời cho đến nay. Tuy nhiên, tôi đã bắt đầu chạy vào các vấn đề gần đây khi tôi muốn nhận được tài liệu tham khảo QJsonObject để sửa đổi thay vì bản sao. Vì vậy, câu hỏi của tôi là, cho các dữ liệu mẫu được cung cấp làm thế nào để tôi có được một tham chiếu QJsonObject để sửa đổi các cặp khóa/giá trị trong đối tượng dữ liệu đồng hồ mong muốn. Vấn đề hiển thị chính nó, IMO do thực tế là bạn có thể thu được QJsonValueRefs, là tham chiếu đến các giá trị mục nhập ... nhưng để thực sự truy cập dữ liệu bên trong này (nếu giá trị là một mảng/đối tượng khác), bạn phải chuyển đổi bằng cách sử dụng toArray Hàm(), toObject() vv Chức năng này chỉ trả về các bản sao chứ không phải các tham chiếu tạo ra một rào cản để lặp lại phân cấp đối tượng với các tham chiếu.

Cách duy nhất tôi tìm ra là tạo một bản sao toàn bộ "CLOCKS" QJsonArray, tìm đối tượng mà tôi muốn rồi xóa nó và chèn lại với dữ liệu đã thay đổi ... và cuối cùng gán toàn bộ mảng trở lại khóa "CLOCKS" trong đối tượng cha. Điều này dường như đủ rườm rà với tôi với tôi rằng tôi cảm thấy như tôi đang làm điều gì đó sai trái và phải có một cách tốt hơn.

Để hỗ trợ điều này đây là những gì mã của tôi trông như thế cho đến nay ... chỉ để thay đổi "VALUE" cho một trong những QJsonObjects đồng hồ:

QJsonArray resets = m_data.value(TAG_RESETS).toArray(); 

    // get a copy of the QJsonObject 
    QJsonObject obj; 
    foreach (const QJsonValue & value, resets) { 
    QJsonObject o = value.toObject(); 
    if (o.value(TAG_ID).toString() == id) { 
     obj = o; 
     break; 
    } 
    } 

    // modify the object 
    obj[TAG_VALUE] = "NEW VALUE"; 

    // erase the old instance of the object 
    for (auto it = resets.begin(); it != resets.end(); ++it) { 
    QJsonObject obj = (*it).toObject(); 
    if (obj.value(TAG_ID).toString() == id) { 
     resets.erase(it); 

     // assign the array copy which has the object deleted 
     m_data[TAG_RESETS] = resets; 
     break; 
    } 
    } 

    // add the modified QJsonObject 
    resets.append(obj); 

    // replace the original array with the array containing our modified object 
    m_data[TAG_RESETS] = resets; 

Tôi biết điều này có thể được rút ngắn một chút nhưng nó vẫn có vẻ như có một cách tốt hơn để thay đổi một giá trị duy nhất trong một hệ thống phân cấp đối tượng QJson mà không cần phải nỗ lực hết sức này !!!

+0

Tôi không tìm thấy bất kỳ cách nào. Nó thật kì lạ. Mô-đun QtScript cũ hỗ trợ điều này, bạn có thể sao chép QScriptValue. Sửa đổi đối tượng của bản sao gây ra sửa đổi tất cả các bản sao khác. QScriptObject nó không hoạt động theo cách đó. –

Trả lời

7

Theo thông tin từ nhà phát triển Qt người thực sự đã viết QJson trong Qt5 -

gì hiện đang có trong Qt là một 'read-only' thực hiện để cung cấp cơ sở phân tích cú pháp. Anh ta có ý định mở rộng thiết kế với sự hỗ trợ 'tài liệu tham khảo' trong tương lai, nhưng nó vẫn chưa được thực hiện.

+0

Được rồi, tôi không thể sửa đổi nhưng, tôi có thể đọc ít nhất không? tôi có nghĩa là sẽ làm việc như một mã? chỉ để đọc? 'json [" aa "]. toObject() [" bb "]. toString();' – Xsmael

+0

vâng, bạn có thể sử dụng nó để đọc, không có probs .. – evilruff

+0

Có vấn đề Qt nào để theo dõi yêu cầu tính năng này không? –

8

Sau khi lãng phí ba giờ trong cuộc đời tôi, tôi có thể xác nhận rằng tính đến hôm nay, điều này vẫn không thể xảy ra với Qt 5.4. Bạn có thể sửa đổi các đối tượng JSON, nhưng không thể sửa đổi các đối tượng JSON lồng nhau.

Vấn đề là các mã như:

json["aa"].toObject()["bb"] = 123;

về cơ bản có nghĩa như sau:

QJsonObject temp = json["aa"].toObject(); 
temp["bb"] = 123; 

và kể từ temp không phải là một tài liệu tham khảo nhưng đối tượng (và toObject() không trả lại một tham chiếu), nhiệm vụ được biên dịch nhưng sau đó bị loại bỏ.

Về cơ bản nó phân tích thành thực tế là không thể lấy tham chiếu đến đối tượng bạn vừa tạo, nghĩa là bạn không thể tạo chúng từ trái sang phải, tức là aa ["bb"] -> aa ["bb" ] ["cc"] v.v. - bạn không thể lấy tham chiếu đến aa ["bb"], chỉ sao chép giá trị của nó.

Điều có thể làm là tạo lại JSON với một giá trị mới được thêm vào, như được mô tả ở đây: https://forum.qt.io/topic/25096/modify-nested-qjsonvalue/4 - lưu ý rằng điều này sẽ tạo lại đối tượng mỗi khi nó được gọi, và về cơ bản là sử dụng bộ nhớ. hiện cho phép.

+0

Điều này đã được cố định bởi QT hay vẫn là một vấn đề? – RvdK

+1

Nó chưa được cố định. Bạn có thể kiểm tra nguyên mẫu hiện tại cho toObject tại đây: http://doc.qt.io/qt-5/qjsonvalue.html#toObject - miễn là toObject trả về một giá trị và không phải là tham chiếu, vấn đề sẽ vẫn còn. Chỉ khi có một hàm trả về QJsonObject và vấn đề sẽ được sửa. –

+0

Đúng, đã làm một số thử nghiệm cho bản thân mình và thực sự không cố định. Rất phiền phức. – RvdK

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