Springboot-如何在PUT请求上传递自定义映射

时间:2018-08-03 17:53:38

标签: spring-boot

传递带有自定义类型的地图的正确方法是什么? 我在Spring Boot应用程序中有一个用于银行逻辑的jar文件,作为外部引用的jar文件。 我应该在jar文件或spring boot应用程序中的哪里定义密钥反序列化器? 这甚至是正确的方法吗?

@PutMapping(value = "/api/bank/coins")
@ResponseBody 
@JsonDeserialize(keyUsing=CoinKeyDeserializer.class)
public Map<Coin, Integer> updateCoins(@RequestBody Map<Coin, Integer> coins) 
{
    return bank.updateCoins(coins);
}

Postman PUT request contains the JSON below.
{
    "Coin [name=QUARTER, value=$0.25]": 100,
    "Coin [name=DIME, value=$0.10]": 100,
    "Coin [name=NICKEL, value=$0.05]": 100,
    "Coin [name=PENNY, value=$0.01]": 100
}

Springboot error:
{
    "timestamp": "2018-07-31T14:56:00.050+0000",
    "status": 500,
    "error": "Internal Server Error",
    "message": "Type definition error: [simple type, class com.zimmy.Coin]; 
    nested exception is 
    com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot 
    find a (Map) Key deserializer for type [simple type, class 
    com.zimmy.Coin]\n at [Source: (PushbackInputStream); line: 1, column: 
    1]", "path": "/api/bank/coins"
}

来自外部jar的类:     包com.zimmy;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.util.Locale;

public class Coin {

    private String name;
    private BigDecimal value;
    private NumberFormat formatter = 
    NumberFormat.getCurrencyInstance(Locale.US);

    public Coin() {
    }

    public Coin(String name, BigDecimal value) {
        this.name = name;
        this.value = value.setScale(2, RoundingMode.HALF_UP);;
    }

    public BigDecimal getValue() {
        return value;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

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

    @Override
    public String toString() {
        return "Coin [name=" + name + ", value=" + formatter.format(value) + 
    "]";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((value == null) ? 0 : value.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;

        Coin other = (Coin) obj;
        if (value == null) {
            if (other.value != null)
                return false;
        } else if (!value.equals(other.value))
            return false;
        return true;
    }

}

2 个答案:

答案 0 :(得分:0)

您的邮递员json应该是这样的

{ {“name” : “quater”, “value” : 0.25} : 10, {“name” : “penny”, “value” : 0.75} : 100}

要与控制器中的请求模型Map<Coin, Integer>匹配,但发布的邮递员示例与Map<String, Integer>匹配。

答案 1 :(得分:0)

我遵循了萨吉布的建议。它可以工作,但是我仍然好奇这是否是最好的方法。

SpringBoot Code:
@PutMapping(value = "/api/bank/coins")
@ResponseStatus(HttpStatus.OK)
@ResponseBody
// @JsonDeserialize(keyUsing=CoinKeyDeserializer.class)
public Map<Coin, Integer> updateCoins(@RequestBody Map<String, Integer> coinsString) 
{
    Map<Coin, Integer> coins = new LinkedHashMap<Coin, Integer>();
    System.out.println("RequestBody: "+coinsString);
    for (Entry<String, Integer> entry : coinsString.entrySet()) {
        String json = entry.getKey();
        System.out.println("Coin JSON: "+json);
        Coin coin = getCoinFromJSON(json);
        coins.put(coin, entry.getValue());
    }
    return bank.updateCoins(coins);
}
private Coin getCoinFromJSON(String json) {
    Coin coin = null;
    ObjectMapper mapper = new ObjectMapper();
    try {
        coin = mapper.readValue(json, Coin.class);
    } catch (JsonGenerationException e) {
        e.printStackTrace();
    } catch (JsonMappingException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return coin;
}

POSTMAN PUT Request:
{
    "{\"name\":\"NINETYC\",\"value\":0.90}":100,
    "{\"name\":\"SEVENTYC\",\"value\":0.70}":100,
    "{\"name\":\"FIFTYC\",\"value\":0.50}":100,
    "{\"name\":\"QUARTER\",\"value\":0.25}":100,
    "{\"name\":\"DIME\",\"value\":0.10}":100,
    "{\"name\":\"NICKEL\",\"value\":0.05}":100,
    "{\"name\":\"PENNY\",\"value\":0.01}":100
}

Springboot Console:
2018-08-04 14:37:03.085  INFO 35760 --- [nio-8081-exec-2] 
o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': 
initialization completed in 13 ms
RequestBody: {{"name":"NINETYC","value":0.90}=100, 
{"name":"SEVENTYC","value":0.70}=100, {"name":"FIFTYC","value":0.50}=100, 
{"name":"QUARTER","value":0.25}=100, {"name":"DIME","value":0.10}=100, 
{"name":"NICKEL","value":0.05}=100, {"name":"PENNY","value":0.01}=100}
Coin JSON: {"name":"NINETYC","value":0.90}
Coin JSON: {"name":"SEVENTYC","value":0.70}
Coin JSON: {"name":"FIFTYC","value":0.50}
Coin JSON: {"name":"QUARTER","value":0.25}
Coin JSON: {"name":"DIME","value":0.10}
Coin JSON: {"name":"NICKEL","value":0.05}
Coin JSON: {"name":"PENNY","value":0.01}