是否有可能使用 Jackson JsonParser

问题描述

我正在尝试使用 Jackson JsonParser一个大型 JSON 文件中一一读取事件。我想将每个事件临时存储在一个对象中,例如 JsonObject 或任何其他我以后想要用于进一步处理的对象。

我之前是一一读取 JSON 事件并将它们存储到我自己的自定义上下文中:Old Post for JACKSON JsonParser Context 工作正常。但是,我想将它们一一存储到 jsonObject 或其他对象中,而不是上下文。

以下是我的示例 JSON 文件

{
   "@context":"https://context.org/context.jsonld","isA":"SchoolManagement","format":"application/ld+json","schemaVersion":"2.0","creationDate":"2021-04-21T10:10:09+00:00","body":{
      "members":[
         {
            "isA":"student","name":"ABCS","class":10,"coaching":[
              "XSJSJ","IIIRIRI"
            ],"dob":"1995-04-21T10:10:09+00:00"
         },{
            "isA":"teacher","department":"computer science","school":{
              "name":"ABCD School"
            },{
            "isA":"boardMember","board":"schoolboard","dob":"1995-04-21T10:10:09+00:00"
         }
      ]
   }
}

有时我只想在我的 member 中存储一个 student,例如 teacherJsonObject

以下是我到目前为止的代码: 将每个事件存储在一个对象中的最佳方法是什么,我以后可以使用它进行一些处理。 然后再次清除该对象并将其用于下一个事件?

public class Main {

    private JSONObject eventInfo;
    private final String[] eventTypes = new String[] { "student","teacher","boardMember" };

    public static void main(String[] args) throws JsonParseException,JsonMappingException,IOException,JAXBException,URISyntaxException {
        // Get the JSON Factory and parser Object
        JsonFactory jsonFactory = new JsonFactory();
        JsonParser jsonParser = jsonFactory.createParser(new File(Main.class.getClassLoader().getResource("inputJson.json").toURI()));
        JsonToken current = jsonParser.nextToken();

        // Check the first element is Object
        if (current != JsonToken.START_OBJECT) {
            throw new IllegalStateException("Expected content to be an array");
        }

        // Loop until the start of the EPCIS EventList array
        while (jsonParser.nextToken() != JsonToken.START_ARRAY) {
            System.out.println(jsonParser.getCurrentToken() + " --- " + jsonParser.getCurrentName());
        }

        // Goto the next token
        jsonParser.nextToken();

        // Call the method to loop until the end of the events file
        eventTraverser(jsonParser);
    }

    // Method which will traverse through the eventList and read event one-by-one
    private static void eventTraverser(JsonParser jsonParser) throws IOException {

        // Loop until the end of the EPCIS events file
        while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
            
            //Is there a possibility to store the complete object directly in an JSON Object or I need to again go through every token to see if is array and handle it accordingly as mentioned in my prevIoUs POST.
            
        }
    }
}

解决方法

在尝试了一些东西后,我能够让它工作。我发布了整个代码,因为它可能对将来的某个人有用,因为我知道找到合适的工作代码示例是多么令人沮丧:

public class Main
{
  public void xmlConverter (InputStream jsonStream) throws IOException,JAXBException,XMLStreamException
  {
    // jsonStream is the input JSOn which is normally passed by reading the JSON file
    
    // Get the JSON Factory and parser Object
    final JsonFactory jsonFactory = new JsonFactory ();
    final JsonParser jsonParser = jsonFactory.createParser (jsonStream);
    final ObjectMapper objectMapper = new ObjectMapper ();

    //To read the duplicate keys if there are any key duplicate json
    final SimpleModule module = new SimpleModule ();
      module.addDeserializer (JsonNode.class,new JsonNodeDupeFieldHandlingDeserializer ());
      objectMapper.registerModule (module);
      jsonParser.setCodec (objectMapper);

    // Check the first element is Object if not then invalid JSON throw error
    if (jsonParser.nextToken () != JsonToken.START_OBJECT)
      {
    throw new IllegalStateException ("Expected content to be an array");
      }

    while (!jsonParser.getText ().equals ("members"))
      {
    //Skipping the elements till members key
    // if you want you can do some process here
    // I am skipping for now
      }

    // Goto the next token
    jsonParser.nextToken ();

    while (jsonParser.nextToken () != JsonToken.END_ARRAY)
      {
    final JsonNode jsonNode = jsonParser.readValueAsTree ();

    //Check if the JsonNode is valid if not then exit the process
    if (jsonNode == null || jsonNode.isNull ())
      {
        System.out.println ("End Of File");
        break;
      }

    // Get the eventType
    final String eventType = jsonNode.get ("isA").asText ();

    // Based on eventType call different type of class
    switch (eventType)
      {
      case "student":
        final Student studentInfo =
          objectMapper.treeToValue (jsonNode,Student.class);
        //I was calling the JAXB Method as I was doing the JSON to XML Conversion
        xmlCreator (studentInfo,Student.class);
        break;
      case "teacher":
        final Teacher teacherInfo =
          objectMapper.treeToValue (jsonNode,Teacher.class);
        xmlCreator (teacherInfo,Teacher.class);
        break;
      }
      }

  }

  //Method to create the XML using the JAXB
  private void xmlCreator (Object eventInfo,Class eventType) throws JAXBException
  {
    private final StringWriter sw = new StringWriter ();

    // Create JAXB Context object
    JAXBContext context = JAXBContext.newInstance (eventType);

    // Create Marshaller object from JAXBContext
    Marshaller marshaller = context.createMarshaller ();

    // Print formatted XML
      marshaller.setProperty (Marshaller.JAXB_FORMATTED_OUTPUT,Boolean.TRUE);

    // Do not add the <xml> version tag
      marshaller.setProperty (Marshaller.JAXB_FRAGMENT,Boolean.TRUE);

    // XmlSupportExtension is an interface that every class such as Student Teacher implements
    // xmlSupport is a method in XmlSupportExtension which has been implemented in all classes

    // Create the XML based on type of incoming event type and store in SW
      marshaller.marshal (((XmlSupportExtension) eventInfo).xmlSupport (),sw);

    // Add each event within the List
      eventsList.add (sw.toString ());

    // Clear the StringWritter for next event
      sw.getBuffer ().setLength (0);

  }
}

这是覆盖 JACKSON 类的类。 如果您的 Json 具有重复的 JSON 密钥,则可以使用此方法。如果您需要,请关注此帖子以获得完整的说明。如果不需要,请跳过此部分并从上述类中删除代码 module 部分: Jackson @JsonAnySetter ignores values of duplicate key when used with Jackson ObjectMapper treeToValue method


@JsonDeserialize(using = JsonNodeDupeFieldHandlingDeserializer.class)
public class JsonNodeDupeFieldHandlingDeserializer extends JsonNodeDeserializer {

  @Override
  protected void _handleDuplicateField(JsonParser p,DeserializationContext ctxt,JsonNodeFactory nodeFactory,String fieldName,ObjectNode objectNode,JsonNode oldValue,JsonNode newValue) {

    ArrayNode asArrayValue = null;

    if (oldValue.isArray()) {
      asArrayValue = (ArrayNode) oldValue;
    } else {
      asArrayValue = nodeFactory.arrayNode();
      asArrayValue.add(oldValue);
    }
    asArrayValue.add(newValue);
    objectNode.set(fieldName,asArrayValue);
  }

}