简体   繁体   English

在Spring Boot Rest Controller中解析Json数组init单个对象

[英]Parse Json array init single object in Spring boot Rest Controller

All I need some help to parse the object on the class base. 我所需要的全部帮助来解析基于类的对象。 I have a list of Imp object. 我有一个Imp对象列表。 i don't want it map all to the class and create the all object. 我不希望它全部映射到类并创建所有对象。 I need only the First object of the Imp in my RtbRequest class. 在RtbRequest类中只需要Imp的First对象

Reason:- why i need to do like that. 原因:-为什么我需要那样做。 In imp json user send the non-number of imp object's in list and required on one object. 在imp json 用户中,将非数字imp对象的in列表发送给一个对象,并且是必需的。 i'd want to parse all. 我想全部解析。 Is this possible 这可能吗

My Pojo Class 我的Pojo课堂

@JsonInclude(JsonInclude.Include.NON_NULL)
public class RtbRequest {

   // number of attribute
    private Imp imp;

    public void setImp(Imp imp) {
        this.imp = imp;
    }

}
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Imp {

   // number of attribute
   @JsonIgnore
   private Map<String, String> impMap = new HashMap<>();
   private String id;
   private Double bidfloor;
    //final-map
    public void setId(String id) {
        log.info("set--id--rtb--Imp");
        this.id = id;
        impMap.put("impid", getId());
    }


}

My Json Object 我的Json对象

{
    "id": "ded06290-f586-45c6-bbcb-015adba03e39",
    "imp": [{
            "id": "1",
            "video": {
                "linearity": 1,
                "maxduration": 120,
                "protocols": [2, 5, 3, 6],
                "w": 1280,
                "h": 720,
                "startdelay": 0,
                "skip": 1,
                "sequence": 1,
                "playbackmethod": [1, 2, 3],
                "api": [2]
            },
            "bidfloor": 0.0,
            "secure": 1

        },
        {
            "id": "2",
            "video": {
                "linearity": 1,
                "maxduration": 120,
                "protocols": [2, 5, 3, 6],
                "w": 1280,
                "h": 720,
                "startdelay": 0,
                "skip": 1,
                "sequence": 1,
                "playbackmethod": [1, 2, 3],
                "api": [2]
            },
            "bidfloor": 0.0,
            "secure": 1
        }
    ]

}

My RestController 我的RestController

@RequestMapping(value= { "/request/{partner}"}, method = RequestMethod.POST)
public Map<String, String> getRtbResponse(@PathVariable String partner, @RequestBody RtbRequest request) {}

JSON serialization works best if you serialize into strong types, so each JSON object will normally map directly to a Java class. 如果将序列化为强类型,则JSON序列化效果最佳,因此每个JSON对象通常都将直接映射到Java类。 If all your items look like: 如果您所有的物品看起来像:

{
    "id": "1",
    "exp": 3600,
    "secure": 0,
    "instl": 1
}

you should create an identical Java class, with getters and setters 您应该使用getter和setter创建相同的Java类

Class Item {
    String id;
    long exp;
    int secure;
    int instl;
    // setters and getter
}

The controller method signature should be: 控制器方法签名应为:

 @RequestMapping(value= { "/request/{partner}"}, method = 
 RequestMethod.POST)
public Map<String, String> getRtbResponse(@RequestBody List<Item> data, @PathVariable String partner) {}

If each partner sends in data in different formats, the solution may depend on weather you need to process the data, or simply store it. 如果每个合作伙伴以不同格式发送数据,则解决方案可能取决于您需要处理或存储数据的天气。 If you 'just' need to store the data and not process it, you can use the fact that all JSON object can be handled as maps, so it is possible to make your controller like this: 如果您只需要存储数据而不进行处理,则可以使用所有JSON对象都可以作为地图处理的事实,因此可以使您的控制器像这样:

 @RequestMapping(value= { "/request/{partner}"}, method = 
 RequestMethod.POST)
public Map<String, String>> getRtbResponse(@RequestBody List<Map<String, Object>> data, @PathVariable String partner) {}

However if you need to process the data in any way, using Map<String, Object> is generally not a good plan. 但是,如果您需要以任何方式处理数据,则使用Map<String, Object>通常不是一个好的计划。

In Java we could create an Interface PartnerItem and multiple subclasses, each matching the data submitted by each partner. 在Java中,我们可以创建一个Interface PartnerItem和多个子类,每个子类与每个伙伴提交的数据匹配。 This is also possible in JSON, but since JSON objects have no name, it needs to be included in some other way. 在JSON中也可以这样做,但是由于JSON对象没有名称,因此需要以其他方式将其包含在内。 Here is a link to a guide that explains how Jackson inheritance works 这是指南的链接,该指南解释了杰克逊继承的工作方式

Note : Personally I never use array as my top level JSON structure when I design APIs, I always use object. 注意 :就我个人而言,在设计API时,我从未将数组用作顶层JSON结构,而是始终使用对象。 The reason is that I can add additional fields to an object, which allows me to mutate the API in a backwards compatible way - this is not possible if your top-level structure is an array. 原因是我可以向对象添加其他字段,这允许我以向后兼容的方式更改API-如果您的顶级结构是数组,则无法实现。

All Sorry for late replay for this issue i handle this by use of Cross filter. 很抱歉,这个问题我以后不能重播,我通过使用交叉滤镜来解决。 I first update my IMP list to Object after that i update the ReadHttpServletRequest stream by adding this Request into do-filer change. 我首先通过将此Request添加到do-filer更改中来更新ReadHttpServletRequest流,然后将我的IMP列表更新为Object

Main Key Point 主要要点

Note:- final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(getNewRequest().getBytes()); 注意:-final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(getNewRequest()。getBytes());

@Component
public class Cross implements Filter {

    private final static Logger log = LoggerFactory.getLogger(Cross.class);

    //********************************
    //           Filter Config      //
    //********************************
    private static Integer count = 0;
    private Long before;


    @Autowired
    ValidatorService validatorService;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException { }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {

        try {

            // response
            log.info("=================Request-Start-"+(count++)+"-=====================");
            before = System.currentTimeMillis();
            ReadHttpServletRequest requestWrapper = new ReadHttpServletRequest((HttpServletRequest) servletRequest);

            HttpServletResponse response = (HttpServletResponse) servletResponse;
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Methods", "POST, GET");
            response.setHeader("Access-Control-Max-Age", "3600");
            response.setHeader("Access-Control-Allow-Headers", "X-requested-with, Content-Type");

            String body = requestWrapper.getNewRequest();
            String header = requestWrapper.getHeader();
            if (body != null && header != null) {
                /*
                * Note:- This below line's first update the request and conver the imp's to imp by getting
                * the single first index object. if the object is not their this will not process ad send the simple same
                * json string for validation if the string valid then dofilter map the json into @Pojo.
                * */
                log.info("New:- "+"header " + header + ", body " + body);
                if (validatorService.isResponseValidator(body, InputType.REQUEST.toString().equals("REQUEST") ? InputType.REQUEST : null)) {
                    filterChain.doFilter(requestWrapper, servletResponse);
                } else {
                    /*
                    * Note:- IF Validator fail this will show error
                    * if imp's size 0 then here
                    * if imp's object not their then here
                    * */
                    response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                    String responseMessage = "{\"result\": \"Oops an error happened!\nSomething bad happened uh-oh!\"}";
                    response.getWriter().print(responseMessage);
                }
            }
        }catch (NullPointerException e) {
            log.error("--Error--> "+ e.getMessage());
            filterChain.doFilter(servletRequest, servletResponse);

        }finally {
            long result = System.currentTimeMillis() - before;
            log.info("Total response time -> (" + (result) + ") miliseconds");
            log.info("=================Request-End=====================");
        }
    }

    @Override
    public void destroy() { }

}


public class ReadHttpServletRequest extends HttpServletRequestWrapper {

    private final static Logger log = LoggerFactory.getLogger(Cross.class);

    private String body = "";
    private String newBody = "";
    private String header = "";
    private final String IMP = "imp";

    public ReadHttpServletRequest(HttpServletRequest request) throws IOException {
        super(request);
        BufferedReader bufferedReader = request.getReader();
        String line;
        StringBuffer stringBuffer = new StringBuffer();
        while ((line = bufferedReader.readLine()) != null) {
            stringBuffer.append(line);
        }
        setBody(stringBuffer.toString());
        // fetch header
        this.setHeader(request.getHeader("x-openrtb-version"));
        log.info("Old:- "+"header " + getHeader() + ", body " + getBody());
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream byteArrayInputStream =
                new ByteArrayInputStream(getNewRequest().getBytes());
        return new ServletInputStream() {
            @Override
            public int read() throws IOException {
                return byteArrayInputStream.read();
            }
            @Override
            public boolean isFinished() { return false; }
            @Override
            public boolean isReady() { return false; }
            @Override
            public void setReadListener(ReadListener listener) {}

        };
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(this.getInputStream()));
    }

    public void setBody(String body) {
        log.info("Body-set");
        this.body = body;
        // set the new body also
        setNewRequest(getUpdateRequestBody(getBody()));
    }
    public void setHeader(String header) {
        log.info("Header-set");
        this.header = header;
    }

    public String getBody() {
        log.info("Body-get");
        return this.body;
    }
    public String getHeader() {
        log.info("Header-get");
        return this.header;
    }

    private String getUpdateRequestBody(String body) {

        JSONObject jsonRequest = (JSONObject) JSONSerializer.toJSON(body);
        /**
         * Find the imp's list and convert into the json-object then add into the request as update's
         * */
        if(jsonRequest.get(IMP) != null) {
            JSONArray jsonArray = jsonRequest.getJSONArray(IMP);
            if(jsonArray != null && (jsonArray.isArray() && jsonArray.size() > 0)) {
                JSONObject impObject = jsonRequest.getJSONArray(IMP).getJSONObject(0);
                // remove the list of imp
                jsonRequest.remove(IMP);
                // add the new one into the json reqeust
                jsonRequest.put(IMP, impObject);
            }
        }
        return jsonRequest.toString();
    }

    private void setNewRequest(String body) {
        log.info("newBody set");
        this.newBody = body;
    }

    public String getNewRequest() {
        log.info("newBody get");
        return this.newBody;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM