private void unmarshal()

in core/camel-support/src/main/java/org/apache/camel/support/processor/RestBindingAdvice.java [180:331]


    private void unmarshal(Exchange exchange, Map<String, Object> state) {
        boolean isXml = false;
        boolean isJson = false;

        String contentType = ExchangeHelper.getContentType(exchange);
        if (contentType != null) {
            isXml = contentType.toLowerCase(Locale.ENGLISH).contains("xml");
            isJson = contentType.toLowerCase(Locale.ENGLISH).contains("json");
        }
        // if content type could not tell us if it was json or xml, then fallback to if the binding was configured with
        // that information in the consumes
        if (!isXml && !isJson) {
            isXml = consumes != null && consumes.toLowerCase(Locale.ENGLISH).contains("xml");
            isJson = consumes != null && consumes.toLowerCase(Locale.ENGLISH).contains("json");
        }

        // set data type if in use
        if (exchange.getContext().isUseDataType()) {
            if (exchange.getIn() instanceof DataTypeAware && (isJson || isXml)) {
                ((DataTypeAware) exchange.getIn()).setDataType(new DataType(isJson ? "json" : "xml"));
            }
        }

        // only allow xml/json if the binding mode allows that
        isXml &= bindingMode.equals("auto") || bindingMode.contains("xml");
        isJson &= bindingMode.equals("auto") || bindingMode.contains("json");

        // if we do not yet know if its xml or json, then use the binding mode to know the mode
        if (!isJson && !isXml) {
            isXml = bindingMode.equals("auto") || bindingMode.contains("xml");
            isJson = bindingMode.equals("auto") || bindingMode.contains("json");
        }

        String accept = exchange.getMessage().getHeader("Accept", String.class);
        state.put(STATE_KEY_ACCEPT, accept);

        // add missing default values which are mapped as headers
        if (queryDefaultValues != null) {
            for (Map.Entry<String, String> entry : queryDefaultValues.entrySet()) {
                if (exchange.getIn().getHeader(entry.getKey()) == null) {
                    exchange.getIn().setHeader(entry.getKey(), entry.getValue());
                }
            }
        }

        // perform client request validation
        if (clientRequestValidation) {
            RestClientRequestValidator.ValidationContext vc = new RestClientRequestValidator.ValidationContext(
                    consumes, produces, requiredBody, queryDefaultValues, queryAllowedValues, requiredQueryParameters,
                    requiredHeaders);
            RestClientRequestValidator.ValidationError error = clientRequestValidator.validate(exchange, vc);
            if (error != null) {
                exchange.getMessage().setHeader(Exchange.HTTP_RESPONSE_CODE, error.statusCode());
                exchange.getMessage().setBody(error.body());
                exchange.setRouteStop(true);
                return;
            }
        }

        String body = null;
        if (ObjectHelper.isNotEmpty(exchange.getIn().getBody())) {
            // okay we have a binding mode, so need to check for empty body as that can cause the marshaller to fail
            // as they assume a non-empty body
            if (isXml || isJson) {
                // we have binding enabled, so we need to know if there body is empty or not
                // so force reading the body as a String which we can work with
                body = MessageHelper.extractBodyAsString(exchange.getIn());
                if (ObjectHelper.isNotEmpty(body)) {
                    if (exchange.getIn() instanceof DataTypeAware dataTypeAware) {
                        dataTypeAware.setBody(body, new DataType(isJson ? "json" : "xml"));
                    } else {
                        exchange.getIn().setBody(body);
                    }
                    if (isXml && isJson) {
                        // we have still not determined between xml or json, so check the body if its xml based or not
                        isXml = body.startsWith("<");
                        isJson = !isXml;
                    }
                }
            }
        }

        // favor json over xml
        if (isJson && jsonUnmarshal != null) {
            // add reverse operation
            state.put(STATE_KEY_DO_MARSHAL, STATE_JSON);
            if (ObjectHelper.isNotEmpty(body)) {
                try {
                    jsonUnmarshal.process(exchange);
                    ExchangeHelper.prepareOutToIn(exchange);
                } catch (Exception e) {
                    exchange.setException(e);
                }
                if (exchange.isFailed()) {
                    // we want to indicate that this is a bad request instead of 500 due to parsing error
                    exchange.getMessage().setHeader(Exchange.HTTP_RESPONSE_CODE, 400);
                }
            }
            if (clientRequestValidation && exchange.isFailed()) {
                // this is a bad request, the client included message body that cannot be parsed to json
                exchange.getMessage().setHeader(Exchange.HTTP_RESPONSE_CODE, 400);
                exchange.getMessage().setBody("Invalid JSon payload.");
                // clear exception
                exchange.setException(null);
                // stop routing and return
                exchange.setRouteStop(true);
                return;
            }
            return;
        } else if (isXml && xmlUnmarshal != null) {
            // add reverse operation
            state.put(STATE_KEY_DO_MARSHAL, STATE_XML);
            if (ObjectHelper.isNotEmpty(body)) {
                try {
                    xmlUnmarshal.process(exchange);
                    ExchangeHelper.prepareOutToIn(exchange);
                } catch (Exception e) {
                    exchange.setException(e);
                }
                if (exchange.isFailed()) {
                    // we want to indicate that this is a bad request instead of 500 due to parsing error
                    exchange.getMessage().setHeader(Exchange.HTTP_RESPONSE_CODE, 400);
                }
            }
            if (clientRequestValidation && exchange.isFailed()) {
                // this is a bad request, the client included message body that cannot be parsed to XML
                exchange.getMessage().setHeader(Exchange.HTTP_RESPONSE_CODE, 400);
                exchange.getMessage().setBody("Invalid XML payload.");
                // clear exception
                exchange.setException(null);
                // stop routing and return
                exchange.setRouteStop(true);
                return;
            }
            return;
        }

        // we could not bind
        if ("off".equals(bindingMode) || bindingMode.equals("auto")) {
            // okay for auto we do not mind if we could not bind
            state.put(STATE_KEY_DO_MARSHAL, STATE_JSON);
        } else {
            if (bindingMode.contains("xml")) {
                exchange.setException(
                        new CamelExchangeException("Cannot bind to xml as message body is not xml compatible", exchange));
            } else {
                exchange.setException(
                        new CamelExchangeException("Cannot bind to json as message body is not json compatible", exchange));
            }
        }

    }