0

In my Gentics Mesh plugin, I'm creating Nodes from json files.

I've created a scripting process that replaces variable placeholders in a json file, with actual values [for example, from a previous node creation event].

This works great if I have a strongly typed object added to the variable resolver...

Because the variable resolver uses reflection to find the property names on a variable value, and does the replacement in json. But if the variable added to the resolver is a JsonObject, the properties I need are not available.

Examples:

I set a variable called 'project' in the resolver, from the output of this method. [projectResponse.rootNode]

private ProjectResponse createProject(String project) {
    ProjectCreateRequest createProject = new ProjectCreateRequest()
            .setName(project)
            .setSchemaRef("folder");
    return this.adminClient.createProject(createProject).blockingGet();
}

Json Files -

First json file works because I added the project NodeReference to the variable resolver -

{
  "parentNode" : {
    "uuid" : "<project.uuid>"
  },
  "schema" : {
    "name" : "folder"
  },
  "language" : "en",
  "fields" : {
    "name" : "node1 - child of project root node"
  }
}

The response of that creation is a JsonObject, which I then pass into the variable resolver.
Then I create a second node.
Note I'm using the generic post method [I don't know how to create a NodeCreateRequest from a json string, which could also solve this]

private JsonObject createNode(String project, String processedNode) {
        JsonObject request = new JsonObject(processedNode);
        JsonObject response = this.adminClient.post(String.format("/%s/nodes", project), request).blockingGet();
        return response;
    }

Second json file doesn't work because node1 is a JsonObject, and doesn't have a uuid property -

{
  "parentNode" : {
    "uuid" : "<node1.uuid>"
  },
  "schema" : {
    "name" : "folder"
  },
  "language" : "en",
  "fields" : {
    "name" : "node2 - child of node1"
  }
}

I can't automatically map the JsonObject to a NodeResponse - And a FieldMap has many different implementations, so I don't know if I could add a Mapper module to fix this.

private NodeResponse createNode(String project, String processedNode) {
        JsonObject request = new JsonObject(processedNode);
        JsonObject response = this.adminClient.post(String.format("/%s/nodes", project), request).blockingGet();
        return response.mapTo(NodeResponse.class);
}

Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance ofcom.gentics.mesh.core.rest.node.FieldMap(no Creators, like default construct, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: com.gentics.mesh.core.rest.node.NodeResponse["fields"])

I think I've solved a similar use case by wrapping a Map in another class, then when the reflection occurs, I return my own property values based on the keys in the Map... but that was C#... and a long time ago.

4

2 回答 2

1

If you have a JSON String you can convert it to any class using the JsonUtil#readValue. I think this should be exposed if you are using the Mesh Rest Client. So in your case, for the request you can use JsonUtil.readValue(json, NodeCreateRequest.class).

If you still want to use the generic methods, I believe the best way is to convert the JsonObject to a String and then use the readValue method.

于 2019-10-21T07:48:43.307 回答
0

Turns out the template engine I'm using can handle a Map object, and access the key like a property.
I fixed it by converting the JsonObject to a HashMap.

return response.mapTo(HashMap.class);
于 2019-10-21T01:29:18.760 回答