首页 > 解决方案 > 使用 json 在 c++ 和 java 之间交换对象

问题描述

我正在尝试使用 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();
};

注册机.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;
...
}

注册器.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 套接字的字符串找到正确的格式。

更新

toString将 c++ 端的方法更改为:

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

toString将 c++ 端的方法更改为:

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);

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

标签: javac++jsonspringqt

解决方案


jsoninUsuario::toString不是有效的 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);

推荐阅读