glaze icon indicating copy to clipboard operation
glaze copied to clipboard

std::pair of structs fails round trip

Open RazielXYZ opened this issue 1 year ago • 2 comments

Tested on msvc, glaze 3.1.9, 3.2.1 and 3.2.5

Given code such as

#include <iostream>
#include "glaze-3.2.5/include/glaze/glaze.hpp"

struct FirstStruct {
    int64_t MyVar {};
};

struct SecondStruct {
    int64_t OtherVar{};
};

int main() {

    std::pair<FirstStruct, SecondStruct> testPair{ {1}, {2} };
    std::string buffer;
    auto ec = glz::write_json(testPair, buffer);
    if (!ec) {
        std::cout << buffer << std::endl;
    } else {
        std::cout << "Error: " << glz::format_error(ec) << std::endl;
    }

    std::pair<FirstStruct, SecondStruct> testPair2;
    auto testPairDeserRes = glz::read_json(testPair2, buffer);
    if (!testPairDeserRes) {
        std::cout << testPair2.first.MyVar << ":" << testPair2.second.OtherVar << std::endl;
    } else {
        std::cout << "Error: " << glz::format_error(testPairDeserRes, buffer) << std::endl;
    }

    return 0;
}

The output is

{"{\"MyVar\":1}":{"OtherVar":2}}
Error: 1:17: expected_quote
   {"{\"MyVar\":1}":{"OtherVar":2}}
                   ^

If using a pair of fundamental types, the round trip succeeds. It looks like this is treated as a map, and the "key" is quoted when serializing, but the deserialization also expects the value to be quoted?

RazielXYZ avatar Aug 15 '24 00:08 RazielXYZ

Yes, this is an active issue here #1000, but thanks for bringing more attention to it.

stephenberry avatar Aug 15 '24 02:08 stephenberry

I see, I wasn't sure if it was related since that mentioned arrays specifically. Thanks!

RazielXYZ avatar Aug 15 '24 02:08 RazielXYZ

It's taken me a while to come back to this, but I've been improving the pair handling.

Glaze treats std::pair as a single element object (key and value). This works well with C++ because types like std::map use std::pair for elements.

A pair of structs like you are using here doesn't make a lot of sense, because the first struct would be the key for the other struct. And, you can't generally decode a string key into an object (struct).

I'm sorry I didn't look into this more carefully before. For your use case you should probably just use a std::tuple<FirstStruct, SecondStruct>. Glaze treats a std::tuple as an array, which will properly roundtrip.

I'm going to close this issue, but definitely comment if there is something that you think ought to be done.

stephenberry avatar Oct 30 '24 19:10 stephenberry