জ্যাকসন টীকাগুলি ব্যবহার করে কোনও সম্পত্তির নেস্টেড মানটিকে কীভাবে মানচিত্র করবেন?


90

ধরা যাক আমি এমন একটি এপিআইতে কল করছি যা কোনও পণ্যের জন্য নিম্নলিখিত JSON এর সাথে সাড়া দেয়:

{
  "id": 123,
  "name": "The Best Product",
  "brand": {
     "id": 234,
     "name": "ACME Products"
  }
}

আমি জ্যাকসনের টীকাগুলি ব্যবহার করে পণ্যের আইডি এবং নামটি ঠিক সূক্ষ্মভাবে মানচিত্র করতে সক্ষম হলাম:

public class ProductTest {
    private int productId;
    private String productName, brandName;

    @JsonProperty("id")
    public int getProductId() {
        return productId;
    }

    public void setProductId(int productId) {
        this.productId = productId;
    }

    @JsonProperty("name")
    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

    public String getBrandName() {
        return brandName;
    }

    public void setBrandName(String brandName) {
        this.brandName = brandName;
    }
}

এবং তারপরে পণ্যটি তৈরি করতে জেএস পদ্ধতিটি ব্যবহার করুন:

  JsonNode apiResponse = api.getResponse();
  Product product = Json.fromJson(apiResponse, Product.class);

তবে এখন আমি কীভাবে ব্র্যান্ডের নামটি দখল করব তা নেওয়ার চেষ্টা করার চেষ্টা করছি, যা নেস্টেড সম্পত্তি। আমি আশা করছিলাম যে এরকম কিছু কার্যকর হবে:

    @JsonProperty("brand.name")
    public String getBrandName() {
        return brandName;
    }

তবে অবশ্যই তা হয়নি। আমি টীকাগুলি ব্যবহার করে যা করতে চাই তার সাধনের কোন সহজ উপায় আছে?

প্রকৃত জেএসওএন প্রতিক্রিয়াটি আমি পার্স করার চেষ্টা করছি খুব জটিল, এবং আমার কেবল একটি একক ক্ষেত্র প্রয়োজন সত্ত্বেও, প্রতিটি উপ-নোডের জন্য একটি সম্পূর্ণ নতুন ক্লাস তৈরি করতে চাই না।


4
আমি github.com/json-path/JsonPath ব্যবহার করে শেষ করেছি - বসন্ত এটি হুডের নীচেও ব্যবহার করে। উদাহরণস্বরূপ, তাদের org.springframework.data.web এ।
dehumanizer

উত্তর:


89

আপনি এটির মতো অর্জন করতে পারেন:

String brandName;

@JsonProperty("brand")
private void unpackNameFromNestedObject(Map<String, String> brand) {
    brandName = brand.get("name");
}

23
তিন স্তরের গভীরতা কেমন?
রবিন ক্যান্টারস

4
@ রবিন কি কাজ করবে না? this.abbreviation = ((Map<String, Object>)portalCharacteristics.get("icon")).get("ticker").toString();
মার্সেলো ডি বিক্রয়

একাধিক মান আনপ্যাক করার জন্য একই পদ্ধতিটি ব্যবহার করা যেতে পারে ... আনপ্যাক ভ্যালুফ্রান্সড্রেসড ব্র্যান্ড - ধন্যবাদ
এমএসঞ্জয়

13

এইভাবে আমি এই সমস্যাটি পরিচালনা করেছি:

Brand শ্রেণি:

package org.answer.entity;

public class Brand {

    private Long id;

    private String name;

    public Brand() {

    }

    //accessors and mutators
}

Product শ্রেণি:

package org.answer.entity;

import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonSetter;

public class Product {

    private Long id;

    private String name;

    @JsonIgnore
    private Brand brand;

    private String brandName;

    public Product(){}

    @JsonGetter("brandName")
    protected String getBrandName() {
        if (brand != null)
            brandName = brand.getName();
        return brandName;
    }

    @JsonSetter("brandName")
    protected void setBrandName(String brandName) {
        if (brandName != null) {
            brand = new Brand();
            brand.setName(brandName);
        }
        this.brandName = brandName;
    }

//other accessors and mutators
}

এখানে, brandউদাহরণটি Jacksonসময়কালে serializationএবং deserializationএড়িয়ে যাওয়া হবে, যেহেতু এটির সাথে টিকা দেওয়া আছে @JsonIgnore

Jacksonপদ্ধতি সঙ্গে সটীক ব্যবহার করবে @JsonGetterজন্য serializationমধ্যে জাভা বস্তুর JSONবিন্যাস। সুতরাং, brandNameসঙ্গে সেট করা হয় brand.getName()

একইভাবে, Jacksonপদ্ধতি সঙ্গে সটীক ব্যবহার করবে @JsonSetterজন্য deserializationএর JSONজাভা বস্তুর মধ্যে বিন্যাস। এই পরিস্থিতিতে, আপনাকে brandঅবজেক্টটি নিজেই ইনস্ট্যান্ট করতে হবে এবং এর nameসম্পত্তিটি সেট করতে হবে brandName

আপনি যদি অধ্যবসায় সরবরাহকারী কর্তৃক এড়াতে চান তবে আপনি @Transientদৃ pers়তা টীকাটি ব্যবহার করতে পারেন brandName


5

নেস্টেড বৈশিষ্ট্য মানচিত্র করতে আপনি জসনপথ-এক্সপ্রেশন ব্যবহার করতে পারেন। আমি মনে করি না কোনও সরকারী সমর্থন আছে ( এই সমস্যাটি দেখুন), তবে এখানে একটি আনুষ্ঠানিক বাস্তবায়ন রয়েছে: https://github.com/elasticpath/json-unmarshaller


1

সেটার পদ্ধতি ব্যবহার করা সবচেয়ে ভাল:

জেএসএন:

...
 "coordinates": {
               "lat": 34.018721,
               "lng": -118.489090
             }
...

ল্যাট বা এলএনজির জন্য সেটার পদ্ধতিটি দেখতে পাবেন:

 @JsonProperty("coordinates")
    public void setLng(Map<String, String> coordinates) {
        this.lng = (Float.parseFloat(coordinates.get("lng")));
 }

যদি আপনার উভয়টি পড়ার প্রয়োজন হয় (যেমন আপনি সাধারণত করেন তবে) একটি কাস্টম পদ্ধতি ব্যবহার করুন

@JsonProperty("coordinates")
public void setLatLng(Map<String, String> coordinates){
    this.lat = (Float.parseFloat(coordinates.get("lat")));
    this.lng = (Float.parseFloat(coordinates.get("lng")));
}

-6

এটিকে সহজ করার জন্য .. আমি কোডটি লিখেছি ... এর বেশিরভাগটি স্ব-বর্ণনামূলক।

Main Method

package com.test;

import java.io.IOException;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class LOGIC {

    public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {

        ObjectMapper objectMapper = new ObjectMapper();
        String DATA = "{\r\n" + 
                "  \"id\": 123,\r\n" + 
                "  \"name\": \"The Best Product\",\r\n" + 
                "  \"brand\": {\r\n" + 
                "     \"id\": 234,\r\n" + 
                "     \"name\": \"ACME Products\"\r\n" + 
                "  }\r\n" + 
                "}";

        ProductTest productTest = objectMapper.readValue(DATA, ProductTest.class);
        System.out.println(productTest.toString());

    }

}

Class ProductTest

package com.test;

import com.fasterxml.jackson.annotation.JsonProperty;

public class ProductTest {

    private int productId;
    private String productName;
    private BrandName brandName;

    @JsonProperty("id")
    public int getProductId() {
        return productId;
    }
    public void setProductId(int productId) {
        this.productId = productId;
    }

    @JsonProperty("name")
    public String getProductName() {
        return productName;
    }
    public void setProductName(String productName) {
        this.productName = productName;
    }

    @JsonProperty("brand")
    public BrandName getBrandName() {
        return brandName;
    }
    public void setBrandName(BrandName brandName) {
        this.brandName = brandName;
    }

    @Override
    public String toString() {
        return "ProductTest [productId=" + productId + ", productName=" + productName + ", brandName=" + brandName
                + "]";
    }



}

Class BrandName

package com.test;

public class BrandName {

    private Integer id;
    private String name;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "BrandName [id=" + id + ", name=" + name + "]";
    }




}

OUTPUT

ProductTest [productId=123, productName=The Best Product, brandName=BrandName [id=234, name=ACME Products]]

6
এটি কাজ করে, তবে আমি এমন একটি সন্ধানের চেষ্টা করছি যেখানে আমার কেবল একটি ক্ষেত্র প্রয়োজন থাকলেও প্রতিটি নোডের জন্য আমাকে নতুন ক্লাস তৈরি করতে হবে না।
কেনসকে

-7

হাই এখানে সম্পূর্ণ কাজের কোড।

// জুনিয়ট টেস্ট ক্লাস

পাবলিক ক্লাস সফট {

@Test
public void test() {

    Brand b = new Brand();
    b.id=1;
    b.name="RIZZE";

    Product p = new Product();
    p.brand=b;
    p.id=12;
    p.name="bigdata";


    //mapper
    ObjectMapper o = new ObjectMapper();
    o.registerSubtypes(Brand.class);
    o.registerSubtypes(Product.class);
    o.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);

    String json=null;
    try {
        json = o.writeValueAsString(p);
        assertTrue(json!=null);
        logger.info(json);

        Product p2;
        try {
            p2 = o.readValue(json, Product.class);
            assertTrue(p2!=null);
            assertTrue(p2.id== p.id);
            assertTrue(p2.name.compareTo(p.name)==0);
            assertTrue(p2.brand.id==p.brand.id);
            logger.info("SUCCESS");
        } catch (IOException e) {

            e.printStackTrace();
            fail(e.toString());
        }




    } catch (JsonProcessingException e) {

        e.printStackTrace();
        fail(e.toString());
    }


}
}




**// Product.class**
    public class Product {
    protected int id;
    protected String name;

    @JsonProperty("brand") //not necessary ... but written
    protected Brand brand;

}

    **//Brand class**
    public class Brand {
    protected int id;
    protected String name;     
}

জুনিট টেস্টকেসের // কনসোল.লগ

2016-05-03 15:21:42 396 INFO  {"id":12,"name":"bigdata","brand":{"id":1,"name":"RIZZE"}} / MReloadDB:40 
2016-05-03 15:21:42 397 INFO  SUCCESS / MReloadDB:49 

সম্পূর্ণ বক্তব্য: https://gist.github.com/jeorfevre/7c94d4b36a809d4acf2f188f204a8058


4
আসল জেএসএন প্রতিক্রিয়াটি আমি মানচিত্রের চেষ্টা করছি খুব জটিল is এটিতে প্রচুর নোড এবং সাবনোড রয়েছে এবং প্রত্যেকের জন্য একটি ক্লাস তৈরি করা খুব বেদনাদায়ক হতে পারে, তবুও যখন বেশিরভাগ ক্ষেত্রে আমার কেবল ট্রিপল নেস্টড নোডের সেট থেকে একক ক্ষেত্রের প্রয়োজন হয়। এক টন নতুন ক্লাস তৈরি না করে কেবল একক ক্ষেত্র পাওয়ার কোনও উপায় নেই?
কেনসকে 4'16

একটি নতুন সফট টিকিট খুলুন এবং আমার সাথে ভাগ করুন, আমি আপনাকে এটিতে সহায়তা করতে পারি। আপনি ম্যাপ করতে চান json স্ট্রাউন্ট ভাগ করুন। :)
জর্জেফ্রেমে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.