【问题标题】:Exchange objects between c++ and java using json使用 json 在 c++ 和 java 之间交换对象
【发布时间】:2020-04-21 08:50:25
【问题描述】:

我正在尝试使用 websockets 和 json 将存储在对象上的数据从 c++/qt 项目交换到 java/spring。通过 websockets 的通信工作正常,但在 java/spring 中,数据以null 的形式到达。

在 c++ 类中,我有类似的东西:

QString Usuario::toString() {
    QString json = "{'email': "+email+"}";
    QJsonDocument document = QJsonDocument::fromJson(json.toUtf8());
    QByteArray prettyPrintedJson = document.toJson(QJsonDocument::Indented);
    return prettyPrintedJson;
}

对于这样的类:

usuario.h

class Usuario
{
private:
    QString email;
public:
    Usuario();
    Usuario(QString email);

    QString getEmail();
    void setEmail(QString email);

    QString toString();
};

registro.h

class Registro
{
private:
    QString token;
    Usuario usuario;
    Produto produto;
    Maquina maquina;
public:
    Registro();
    Registro(QString token, Usuario usuario, Produto produto, Maquina maquina);
    Registro(Usuario usuario, Produto produto, Maquina maquina);

    QString getToken();
    void setToken(QString token);

    Usuario getUsuario();
    void setUsuario(Usuario usuario);

    Produto getProduto();
    void setProduto(Produto produto);

    Maquina getMaquina();
    void setMaquina(Maquina maquina);

    QString toString();
};

在java项目中,我有这样的东西:

@Component
public class CheckRegistro extends TextWebSocketHandler {
...
    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) throws InterruptedException, IOException {
    Registro value = new Gson().fromJson(message.getPayload(), Registro.class);
    System.out.println("registro -> " + value);

    String email_usuario = value.getUsuario().getEmail();
    Usuario usuario = usuarioServ.findBy("email", email_usuario);

    String nome_produto = value.getProduto().getNome();
    Produto produto = produtoServ.findBy("nome", nome_produto);

    Cliente cliente = clienteServ.findBy("usuario", usuario);
    if(cliente.produtosComprados().contains(produto))
      value = registroServ.findBy("produto", produto);

    String result = new Gson().toJson(value);
        session.sendMessage(new TextMessage(result));
    }
...
}

以及类似的课程:

usuario.java

@Entity
public class Usuario extends Model implements UserDetails {
  @Id
  @GeneratedValue(strategy=GenerationType.IDENTITY)
  private Integer id;

  @Column
  private String username;

  @Column
  private String password;

  @Column
  private String firstName;

  @Column
  private String lastName;

  @Column
  private String email;
...
}

registro.java

@Entity
public class Registro extends Model{
  @Id
  @GeneratedValue(strategy=GenerationType.IDENTITY)
  private Integer id;

  @Column
  private String token;

  @OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
  private Usuario usuario;

  @OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
  private Produto produto;

  @OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
  private Maquina maquina;
...
}

(作为记录,一些类,如usuario,在java 中的字段比c++ 多;其他类,如registro,在c++ 端或java 端都有相同的字段)。

有人可以提示我这里有什么问题吗?我知道有一些库可以自动将 c++ 对象序列化为 json,但我不知道是否可以在不向我的项目中添加第三方组件的情况下做到这一点,只需为发送到 java 套接字的字符串找到正确的格式。

更新

我把c++端的toString方法改成这样的:

QString Registro::toString() {
    QJsonObject json{
      { "token", token },
      { "usuario", usuario.toString() },
      { "produto", produto.toString() },
      { "maquina", maquina.toString() }
    };
    QJsonDocument jsonDoc;
    jsonDoc.setObject(json);
    QByteArray prettyPrintedJson = jsonDoc.toJson(QJsonDocument::Indented);
    return prettyPrintedJson;
}

现在,在 java 端,json 字符串是这样打印的:

"registro": "{\n    \"maquina\": \"{\\n    \\\"cpuArch\\\": \\\"x86_64\\\",\\n    \\\"hostName\\\": \\\"DESKTOP-7GAPC4K\\\",\\n    \\\"kernelType\\\": \\\"windows\\\",\\n    \\\"kernelVersion\\\": \\\"10\\\",\\n    \\\"productName\\\": \\\"Windows 10 Version 1909\\\",\\n    \\\"ram\\\": \\\"RAM: 16030 MB\\\",\\n    \\\"uniqueId\\\": \\\"c69d8cc7-8e66-4ea3-964a-792b2c2a6f80\\\"\\n}\\n\",\n    \"produto\": \"{\\n    \\\"nome\\\": \\\"prod1\\\"\\n}\\n\",\n    \"token\": \"\",\n    \"usuario\": \"{\\n    \\\"email\\\": \\\"klebermo@gmail.com\\\"\\n}\\n\"\n}\n"
}

更新 2

我把c++端的toString方法改成这样:

QString Registro::toString() {
    return "{ \"token\": \""+token+"\", \"usuario\": "+usuario.toString()+", \"produto\": "+produto.toString()+", \"maquina\": "+maquina.toString()+" }";
}

现在在 java 端我得到了一个有效的 json,但是在这里:

Registro value = new Gson().fromJson(message.getPayload(), Registro.class);

String email_usuario = value.getUsuario().getEmail();
Usuario usuario = usuarioServ.findBy("email", email_usuario);

String nome_produto = value.getProduto().getNome();
Produto produto = produtoServ.findBy("nome", nome_produto);

我正在为value.getUsuario().getEmail() 获得一个NullPointerException。我真的需要从 c++ 端发送一个包含 java 类的所有字段的类吗?有什么方法可以让我只发送带有此查询所需字段的类?或者这不是问题?

【问题讨论】:

  • 打印到达java端的字符串,看看是不是有效的json字符串
  • 您可能认为使用合适的 JSON 库没有多大价值,但这看起来确实可以使用。此外,您可能更喜欢protocolbuffers 或flatbuffers 之类的东西。
  • 让两个程序通信时的第一步是指定数据的确切格式,即 JSON。我不是指“JSON”,而是{ "foo": "Hello", "bar": 42 }。那么您希望传输什么样的 JSON 文本呢? --- 研究反序列化时的第 2 步发出它以验证您获得了预期的 JSON 文本。 --- 第 3 步是测试接收方如何生成 JSON 文本,即使用这些类在 Java 中构建测试数据并生成 JSON,以验证这些类是否与预期的 JSON 匹配。
  • 你现在最大的问题应该是:我的客户端错了还是我的服务器错了?这就是为什么在一起测试两个新组件之前,首先手动测试一个新服务器会有所帮助,方法是向它发送一些你知道是正确的手工制作的 JSON。使用调试器在调用 new Gson().fromJson 之前和之后直观地检查输入。

标签: java c++ json spring qt


【解决方案1】:

Usuario::toString 中的json 不是有效的 JSON。 QJsonDocument::fromJson 解析失败时返回null

假设 email 没有被引用,你需要:

QString json = "{\"email\": \""+email+"\"}";

另外,更安全、更简单的方法是使用 JSON API:

QJsonObject json{
  { "email", email }
};
QJsonDocument document = QJsonDocument::fromJson(json);
QByteArray prettyPrintedJson = document.toJson(QJsonDocument::Indented);

【讨论】:

  • 在我发布代码之前我已经尝试过,并且得到了相同的结果。我实际上首先使用return "{...}";之类的东西,因为不工作尝试QJsonDocumentQJsonObject在返回之前解析字符串,看看是否会返回正确的json字符串。
  • 请使用您尝试过的确切代码发布minimal reproducible example,您可能还需要进行一些错误检查,QJsonDocument::fromJson 解析失败似乎是最有可能的嫌疑人
  • 另外,我在尝试在 java 端转换为 java objct 之前打印 json 字符串,并到达所有内容,` included, but after the Registro value = new Gson().fromJson(message.getPayload(), Registro .class);` 对象获得null 值。
猜你喜欢
  • 2011-01-15
  • 2013-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-30
  • 1970-01-01
  • 2011-10-06
相关资源
最近更新 更多