You need to parse such complex JSON:

{ "receiveData": { "iBusData": { "requestUID": "44bd8a65-d128-48a4-b070-5f90fc5a7674", "messageKind": "PublishedData", "sender": "ST-DELLIN-307", "senderDateTime": "2018-11-07T10:43:41", "typeName": "typeInvoice", "currentSenderApplication": "GP", "objectUID": "322dd3cf-ae4c-4fcc-b785-c2b7698b85b4", "data": { "invoice": { "uid": "322dd3cf-ae4c-4fcc-b785-c2b7698b85b4", "presentation": "Test_Invoice", "date": "2018-11-07T10:43:42", "number": "Test_Invoice", "marked": false, "posted": false, "senderCityUID": "d645a316-564b-4f38-b0b6-4a1541eb70ce", "receiverTerminalUID": "d8bd5e84-c604-4125-aa2b-55a6f23f9e85", "receiverCityUID": "e94042e3-d88e-4097-9349-878989ad28c1", "cargoUID": "21e8eb95-b0aa-477c-b756-e7304921a3d2", "amount": 1, "amountExtraLarge": 1, "netWeight": 1, "netWeightExtraLarge": 1, "grossWeight": 1, "netVolume": 1, "netVolumeExtraLarge": 1, "grossVolume": 1, "declaredValue": 1, "contractorSenderUID": "e5a4a6ff-2a74-46ac-9e98-7a6cab5dc388", "contractorReceiverUID": "993fb6ed-70cc-4b47-87b6-7e0a82affdb2", "contractorPayerUID": "7b60e946-d327-44d4-a0a5-2ebf5ef1ad1c", "contractorSenderIssueUID": "ef0453ff-c8df-4fd1-95ab-7943baee9c71", "contractorReceiverIssueUID": "aaf30c1d-8d8b-4cf9-a1a1-04d8b3d0eab3", "actualReceiver": "Test_Invoice", "freightInKops": 1, "deliveryTimeInsuranceSum": 1, "terminalUID": "47e1481c-1191-49ba-ad11-aceb46284fca", "cargoInsuranceSum": 1, "personalID": null, "senderCityName": "Test_Invoice", "senderCityKLADR": "Test_Invoice", "receiverCityName": "Test_Invoice", "receiverCityKLADR": "Test_Invoice", "transportationCostOnReceiving": 1, "transportationCostOnIssuing": 1, "invoiceUID": "35faff4b-85e3-428b-ab09-4462f118a585" } } } } } 

The difficulty is that this data must be processed as follows:

  • Map JSON with nesting on an object without nesting containing the same fields
  • Take the hash from the nested data object and write it to the Java object field.

How can this be done using deserialization libraries such as Jackson or Gson? There are many examples on the Internet of how embedded json is converted to an object with the same nesting. But I need more complex operations.

  • one
    Possible duplicate question: Parse Json with GSON (Java) library - And
  • @And, there json with nesting parsitsya in the hierarchy of objects. I don't need a hierarchy. The parsed json must be stored in the database as key-value pairs without nesting and validated. - typemoon
  • Duck redo as it should, I hope there are hands. no one will write anything for you. - And
  • @typemoon not in a specific object but in JsonElement - Tsyklop

2 answers 2

We recreate a similar JSON structure in the POJO class, and already parses the response so

 MyPojo string = new Gson().fromJson(jsonStr, MyPojo.class); 

Convert POJO class back

 String jsonStr = new Gson().toJson(myPojo); 

By "not nesting" - as an option, create additional. a class with the function of converting the resulting object into a new one without nesting and back (mapstruct will help with this), and there are already hashes and what you already want to do with it.

    (Jackson) The @JsonDeserialize annotation (using = DataDeserializer.class) can help you, where the DataDeserializer is a deserializer in which you can write any conversion logic. As an example, we create a generic class that climbs all the classes and collects the lowest fields.

     import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.time.LocalDateTime; import java.util.Iterator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.TreeNode; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; public class CustomDeserializer<T> extends StdDeserializer<T> { protected CustomDeserializer() { super(LocalDateTime.class); } @Override public T deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { try { final T instance = ((Class< T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]) .newInstance(); final TreeNode treeNode = jsonParser.readValueAsTree(); parseNode(treeNode, instance); return instance; } catch (NoSuchFieldException | IllegalAccessException | InstantiationException e) { throw new RuntimeException(e); } } private void parseNode(final TreeNode treeNode, final T instance) throws IOException, NoSuchFieldException, IllegalAccessException { final Iterator<String> names = treeNode.fieldNames(); while (names.hasNext()) { final String nodeName = names.next(); final TreeNode nextNode = treeNode.get(nodeName); if (nextNode.isObject()) { parseNode(nextNode, instance); } else { final String value = nextNode.toString(); final Field declaredField = Data.class.getDeclaredField(nodeName); final Class<?> fieldType = declaredField.getType(); final ObjectMapper objectMapper = new ObjectMapper(); final Object deserializedValue = objectMapper.readValue(value, fieldType); declaredField.setAccessible(true); declaredField.set(instance, deserializedValue); } } } } 

    Next, we create an inheritor with the generic type of the type we need:

     public class DataDeserializer extends CustomDeserializer<Data> {} 

    Then mark our class annotation:

     @JsonDeserialize(using = DataDeserializer.class) public class Data {... 

    Well, parsim:

     final ObjectMapper objectMapper = new ObjectMapper(); try { final Data data = objectMapper.readValue("JSON_VALUE", Data.class); } catch (IOException e) { ... } 

    C simple fields should work. Theoretically, it is possible to filter objects whose fields are not required to pick up.