Javaシーケンス化編のJson解析ツールJackson

9290 ワード

jsonの解析パッケージ:


    com.fasterxml.jackson.core
    jackson-core
    2.9.6



    com.fasterxml.jackson.core
    jackson-annotations
    2.9.6



    com.fasterxml.jackson.core
    jackson-databind
    2.9.6


Jacksonの基本的な応用:


JsonNodeクラスは、JacksonのJsonコンテンツをメモリに逆シーケンスするメモリデータ構造表現である.たとえば、テストのJsonコンテンツについて:
{
  "name" : "test",
  "value" : 20,
  "address" : [
    {
     "addressId" : "0001" 
    },
    {
    "addressId" : "0002"
    }
  ]
}

jsonコンテンツをメモリに逆シーケンス化すると、ツリー構造を操作してjsonコンテンツを読み取ることができます.
String name = node.get("name").asText();
Integer value = node.get("value").asInt();
Iterator addressNodes = node.get("address").elements();
String address = addressNodes.next().get("addressId").asText();

上からjacksonはノードの位置決めとタイプ変換を容易に行うことができることが分かった.
jsonコンテンツをJsonNodeに変換するにはどうすればいいですか?
  • ファイル文字列解析
  • public static JsonNode str2JsonNode(String str) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.readTree(str);
    }
    
    
  • stream解析
  • public static JsonNode str2JsonNode(InputStream stream) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.readTree(stream);
    }
    
  • file解析
  • public static JsonNode str2JsonNode(File file) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.readTree(file);
    }
    
  • reader解析
  • public static JsonNode str2JsonNode(Reader reader) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.readTree(reader);
    }
    
  • bytes解析
  • public static JsonNode str2JsonNode(byte[] datas) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.readTree(datas);
    }
    

    Jsonと基本タイプの相互変換:


    readValueメソッドは、文字列を指定したシーケンスにシーケンス化するのに役立ちます.
     public static Object json2Object(String str) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode node = objectMapper.readTree(str);
        if(node.isObject()){
            return objectMapper.readValue(str, Map.class);
        }else if(node.isArray()){
            return objectMapper.readValue(str, List.class);
        }else{
            if (node.isInt()) {
                return node.asInt();
            } else if (node.isLong()) {
                return node.asLong();
            } else if (node.isDouble()) {
                return node.asDouble();
            } else if(node.isTextual()) {
                return node.asText();
            } else if (node.isNull()){
                return null;
            }
            else {
                throw new IOException("Json node exception type :  " + node.numberType());
            }
        }
    }
    

    たとえば、上の文字列を一般的なMap構造に解析します.
    Map map = JsonUtil.json2Bean(str, Map.class);
    System.out.println(map.get("address"));
    List> list = (List>)map.get("address");
    System.out.println(list.get(1).get("addressId"));
    

    もちろん、通常のタイプをwriteValueでStringに変換して印刷することもできます.
    public static String object2Str(Object object, boolean prettyPrint) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
    
        //       
        if(prettyPrint){
            ObjectWriter write = objectMapper.writerWithDefaultPrettyPrinter();
            return write.writeValueAsString(object);
        }
        //     
        return objectMapper.writeValueAsString(object);
    }
    

    StringとBeanの相互変換

  • 変換ツール方法:
  • public static  T str2Bean(String str, Class beanClass) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        return mapper.readValue(str, beanClass);
    }
    

    string->beanをjsonStrごとに対応するbean classを作成する必要があります.
    例:
    {
      "name" : "test",
      "value" : 20
    }
    

    対応するBeanは次のとおりです.
    public class Persion {
        private String name;
        private int value;
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setValue(int value) {
            this.value = value;
        }
        
    }
    
    Persion persion = JsonUtil.str2Bean(str, Persion.class);によって、このとき、setter法によってjsonコンテンツがPersionクラスの対応するフィールドに注入される.
    jsonのkeyがBeanのフィールド名に対応していない場合は、@JsonProperty注釈で対応関係を宣言できます.@JsonProperty注記は、gettersetter、またはコンストラクション関数パラメータに使用することができる.例:
    public class Persion {
        private String name;
        private int value;
    
        @JsonProperty("v-name")
        public void setName(String name) {
            this.name = name;
        }
    
        @JsonProperty("v-value")
        public void setValue(int value) {
            this.value = value;
        }
    }
    
  • 未知のフィールドを除外@JsonIgnoreProperties(ignoreUnknown=true)
  • jsonにbean宣言を持つフィールドが出ている場合もあれば、別の情報が出ている場合もありますが、これらの情報は私たちの関係ではありません.この場合、この部分を捨てる必要があります.クラスの開始時に@JsonIgnoreProperties(ignoreUnknown=true)注釈を使用して、一致しないフィールドや変換に失敗したフィールドを無視することができます.
    @JsonIgnoreProperties(ignoreUnknown = true)
    public class Persion {
        private String name;
        private int value;
    
        @JsonProperty("v-name")
        public void setName(String name) {
            this.name = name;
        }
    
        @JsonProperty("v-value")
        public void setValue(int value) {
            this.value = value;
        }
    }
    
  • カスタムシリアル番号と逆シーケンス化方法:
  • jsonとbeanは単純な対応関係ではない場合があり、逆シーケンス化プロセスは、例えば、このjsonコンテンツの開始に困難があることが多い.
    {
      "name" : "test",
      "value" : 20,
      "address" : [
        {
         "addressId" : "0001" 
        },
        {
        "addressId" : "0002"
        }
      ]
    }
    

    私たちの対応beanは:
    public class Persion {
        private String name;
        private int value;
        private List
    address; }
    public class Address {
        private String addressId;
    
        public void setAddressId(String addressId) {
            this.addressId = addressId;
        }
    }
    

    通常、addressフィールドはListタイプにマッピングされますが、ここではListに自動的に変換する必要があります.この場合、逆シーケンス化プロセスをカスタマイズする必要があります.
    逆シーケンス化クラスは、JsonDeserializerの汎用対応する逆シーケンス化の戻りタイプを継承する必要があります.
    逆シーケンス化ツールクラス
    public class AddressDeserde extends JsonDeserializer {
        public List deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
            ObjectMapper mapper = new ObjectMapper();
            JsonNode nodes = mapper.readTree(jsonParser);
    
            List
    addresses = new LinkedList
    (); for(JsonNode node : Lists.newArrayList(nodes.elements())){ System.out.println(node.toString()); addresses.add(JsonUtil.str2Bean(node.toString(), Address.class)); } return addresses; } }

    その後、beanのフィールドに逆シーケンス化ツールを指定できます.
    @JsonIgnoreProperties(ignoreUnknown = true)
    public class Persion {
        private String name;
        private int value;
        private List
    address; @JsonProperty("v-name") public void setName(String name) { this.name = name; } @JsonProperty("v-value") public void setValue(int value) { this.value = value; } @JsonProperty("address") @JsonDeserialize(using = bean.AddressDeserde.class) public void setAddress(List
    address) { this.address = address; } @Override public String toString() { return "Persion{" + "name='" + name + '\'' + ", value=" + value + ", addresses=" + address + '}'; } }

    この時に使えます.
    同様に、シーケンス化方式をカスタマイズするには、JsonSerializer抽象メソッドを継承する必要があります.
    例えば、addressのフィールドのシーケンス化プロセス:
    public class AddressSerde extends JsonSerializer> {
        @Override
        public void serialize(List
    addresses, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { jsonGenerator.writeStartArray(); for(Address address : addresses){ jsonGenerator.writeObject(address); } jsonGenerator.writeEndArray(); } }
    getterの方法にシーケンス化を加えることができます.
    @JsonProperty("v-address")
    @JsonSerialize(using = bean.AddressSerde.class)
    public List
    getAddress() { return address; }

    そしてListの解析に成功しました