Как передать Map Serializable объекта как JSON в теле запроса - PullRequest
0 голосов
/ 20 мая 2019

Классы моделей выглядят так: MailFilterCondition имеет карту EmailCondition, где Filter - это класс, а MailAttributes и Operator - перечисления:

public class EmailCondition implements Serializable {
private static final long serialVersionUID = -5429392022485346125L;
private Filter.MailAttributes key;
private Filter.Operator op;
private String value;

public Filter.MailAttributes getKey() {
    return key;
}

public void setKey(Filter.MailAttributes key) {
    this.key = key;
}

public Operator getOp() {
    return op;
}

public void setOp(Operator op) {
    this.op = op;
}

public String getValue() {
    return value;
}

public void setValue(String value) {
    this.value = value;
}

@Override
public String toString() {
    return "EmailCondition [key=" + key + ", op=" + op + ", value=" + value + "]";
}
}

public class MailFilterCondition implements Serializable {
private static final long serialVersionUID = -2691329267596354267L;
private int automationId;
private Map<String, EmailCondition> emailConditionMap;
private String filterString;

public int getAutomationId() {
    return automationId;
}

public void setAutomationId(int automationId) {
    this.automationId = automationId;
}

public Map<String, EmailCondition> getEmailConditions() {
    return emailConditionMap;
}

public void setEmailConditions(Map<String, EmailCondition> emailConditionMap) {
    this.emailConditionMap = emailConditionMap;
}

public String getFilterString() {
    return filterString;
}

public void setFilterString(String filterString) {
    this.filterString = filterString;
}

@Override
public String toString() {
    return "MailFilterCondition [automationId=" + automationId + ", emailConditions=" + emailConditionMap
            + ", filterString=" + filterString + "]";
}
}

Контроллер:

@PostMapping(value = "/email")
public void createAutomationFilter(@RequestParam(value="automation_id") int automationId, @RequestBody MailFilterCondition filterData) {

    System.out.println(filterData);
}

Тело запроса:

{
"automationId": 123,
"filterString": "(c1_and_c2)_or_(c1_and_c3)",
"emailConditionMap": 
{
    "c1":{
        "key": "from",
        "op": "contains",
        "value": "jhon"
    },

    "c2":{
        "key": "from1",
        "op": "starts",
        "value": "ron"
    },

    "c3":{
        "key": "from",
        "op": "contains",
        "value": "payment"
    }
}
}

Фильтр перечислений:

public class Filter {
public enum Operator {
    contains("contains"), starts("starts"), ends("ends"), gt("gt"), gteq("gteq"), lt("lt"), lteq("lteq"), eq("eq"),
    inlist("inlist"), pattern("pattern");
    private final String operator;

    private Operator(String opt) {
        this.operator = opt;
    }

    public String getValue() {
        return this.operator;
    }
}

public enum MailAttributes {
    from("from"), to("to"), subject("subject"), body("body"), received_time("received_time");
    private final String attribute;

    private MailAttributes(String attribute) {
        this.attribute = attribute;
    }

    public String getValue() {
        return this.attribute;
    }
}

public enum LogicOperator {
    AND("_and_"), OR("_or_");
    private final String operator;

    private LogicOperator(String opt) {
        this.operator = opt;
    }

    public String getValue() {
        return this.operator;
    }
}
}

Вывод:

MailFilterCondition [automationId=123, emailConditions=null, filterString=(c1_and_c2)_or_(c1_and_c3)]

При передаче пары ключ-значение в json атрибут карты становится нулевым.Я пробовал все, но каждый раз emailConditions печатает ноль.

Ответы [ 3 ]

0 голосов
/ 20 мая 2019

Вам нужно использовать Джексона Marshalling. Он автоматически преобразует объект перед отправкой в ​​теле запроса. Джексон использует геттеры и сеттеры, поэтому ваш объект должен иметь их.

0 голосов
/ 20 мая 2019
@PostMapping(value = "/email")
public void createAutomationFilter(@RequestParam(value="automation_id") int automationId, @RequestBody MailFilterCondition filterData) {

    System.out.println(filterData);
}

Здесь в методе createAutomationFilter вы передаете @RequestParam(value="automation_id") int automationId в качестве параметра, что неверно, так как вы отправляете все параметры в теле запроса в Postman. Таким образом, вы должны отобразить все параметры в один Model класс (т.е. MailFilterCondition) и с помощью @RequestBody аннотация. Пожалуйста, смотрите ниже контроллер.

Контроллер:

import javax.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value = "/mail")
public class TestController {

    @PostMapping(value = "/create", produces = { "application/json" })
    public void createAutomationFilter(@RequestBody final MailFilterCondition emailConditionMap,
            final HttpServletRequest request) {
      System.out.println(emailConditionMap);

    }
}

В этой модели MailFilterCondition ваш установщик и получатель для поля emailConditionMap не подходят.

public Map<String, EmailCondition> getEmailConditions() {
    return emailConditionMap;
}

public void setEmailConditions(Map<String, EmailCondition> emailConditionMap) {
    this.emailConditionMap = emailConditionMap;
}

Обновите свой установщик и получатель с помощью (Spring используется для отображения полей с точно таким же именем установщиков полей)

   public Map<String, EmailCondition> getEmailConditionMap() {
    return emailConditionMap;
     }

   public void setEmailConditionMap(Map<String, EmailCondition> 
     emailConditionMap) {
    this.emailConditionMap = emailConditionMap;
    }

Модель: MailFilterCondition

import java.io.Serializable;
import java.util.Map;

public class MailFilterCondition implements Serializable {
    private static final long serialVersionUID = -2691329267596354267L;
    private int automationId;
    private Map<String, EmailCondition> emailConditionMap;
    private String filterString;

    public int getAutomationId() {
        return automationId;
    }

    public void setAutomationId(int automationId) {
        this.automationId = automationId;
    }

    public Map<String, EmailCondition> getEmailConditionMap() {
        return emailConditionMap;
    }

    public void setEmailConditionMap(Map<String, EmailCondition> emailConditionMap) {
        this.emailConditionMap = emailConditionMap;
    }

    public String getFilterString() {
        return filterString;
    }

    public void setFilterString(String filterString) {
        this.filterString = filterString;
    }

    @Override
    public String toString() {
        return "MailFilterCondition [automationId=" + automationId + ", emailConditions=" + emailConditionMap
                + ", filterString=" + filterString + "]";
    }
}

В модели EmailCondition, я передаю String как параметр в

public void setKey(String key) {
    this.key = Filter.MailAttributes.valueOf(key);
}

public void setOp(String op) {
    this.op = Filter.Operator.valueOf(op);
}

как вы можете видеть в теле запроса, вы передаете key и op значение как String, Эти значения не являются каким-либо пользовательским классом Java. Во время выполнения Spring не может определить тип, который вы передаете

public void setKey(Filter.MailAttributes key) {
    this.key = key;
}

public void setOp(Operator op) {
    this.op = op;
}

Насколько мне известно, вы также можете связать эти поля с помощью @InitBinder аннотации.

Модель: EmailCondition

import java.io.Serializable;

import com.spring.web.controller.Filter.MailAttributes;
import com.spring.web.controller.Filter.Operator;

public class EmailCondition implements Serializable {

    private static final long serialVersionUID = -5429392022485346125L;
    private Filter.MailAttributes key;
    private Filter.Operator op;
    private String value;

    public void setKey(String key) {
        this.key = Filter.MailAttributes.valueOf(key);
    }

    public void setOp(String op) {
        this.op = Filter.Operator.valueOf(op);
    }

    public void setValue(String value) {
        this.value = value;
    }

    public MailAttributes getKey() {
        return key;
    }

    public Operator getOp() {
        return op;
    }

    public String getValue() {
        return value;
    }

    @Override
    public String toString() {
        return "EmailCondition [key=" + key + ", op=" + op + ", value=" + value + "]";
    }
}

Модель: Filter

public class Filter {

    public enum Operator {
        contains("contains"), starts("starts"), ends("ends"), gt("gt"), gteq("gteq"), lt("lt"), lteq("lteq"), eq(
                "eq"), inlist("inlist"), pattern("pattern");
        private final String operator;

        private Operator(String opt) {
            this.operator = opt;
        }

        public String getValue() {
            return this.operator;
        }
    }

    public enum MailAttributes {

        from("from"), to("to"), subject("subject"), body("body"), received_time("received_time");
        private final String attribute;

        private MailAttributes(String attribute) {
            this.attribute = attribute;
        }

        public String getValue() {
            return this.attribute;
        }
    }

    public enum LogicOperator {
        AND("_and_"), OR("_or_");
        private final String operator;

        private LogicOperator(String opt) {
            this.operator = opt;
        }

        public String getValue() {
            return this.operator;
        }
    }
}

Вы можете отправить ajax запрос, как показано ниже:

var payLoad = {

                "automationId": 123,
                "filterString": "(c1_and_c2)_or_(c1_and_c3)",
                "emailConditionMap": 
                {
                    "c1":{
                        "key": "from",
                        "op": "contains",
                        "value": "jhon"
                    },

                    "c2":{
                        "key": "to",
                        "op": "starts",
                        "value": "ron"
                    },

                    "c3":{
                        "key": "subject",
                        "op": "ends",
                        "value": "payment"
                    }
                }

           };

    $.ajax({
        url: appContextJs+"/mail/create",
        type: 'POST',
        contentType: 'application/json',
        data: JSON.stringify(payLoad),
        success: callbackfunction
    });

appContextJs: в качестве базового URL, например: http://localhost:8080/webapp

Пожалуйста, не забудьте установить contentType как application/json в Почтальоне

Выход на консоль почтальона:

{
    "automationId": 123,
    "emailConditionMap": {
        "c1": {
            "key": "from",
            "op": "contains",
            "value": "jhon"
        },
        "c2": {
            "key": "to",
            "op": "starts",
            "value": "ron"
        },
        "c3": {
            "key": "subject",
            "op": "ends",
            "value": "payment"
        }
    },
    "filterString": "(c1_and_c2)_or_(c1_and_c3)"
}

Выход консоли Eclipse:

MailFilterCondition [automationId=123, emailConditions={c1=EmailCondition [key=from, op=contains, value=jhon], c2=EmailCondition [key=to, op=starts, value=ron], c3=EmailCondition [key=subject, op=ends, value=payment]}, filterString=(c1_and_c2)_or_(c1_and_c3)]
0 голосов
/ 20 мая 2019

У вас есть правильные методы получения / установки в классах? Я не уверен, что такое класс Filter, но изменив эти два поля на String, он работает отлично. Так что проблема может быть там.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...