我正在重寫一些使用jackson 將json 決議為scala circe 的java 代碼。
javaDevice類是這樣的-
package forjava;
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
@JsonInclude(Include.NON_NULL)
@JsonPropertyOrder({"ua", "dnt", "ip", "devicetype"})
public class Device implements Serializable {
@JsonProperty("ua")
private String ua;
@JsonProperty("dnt")
private Integer dnt;
@JsonProperty("ip")
private String ip;
@JsonProperty("devicetype")
private Integer devicetype;
@JsonIgnore
private Map<String, Object> additionalProperties = new HashMap();
@JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
@JsonAnySetter
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
private static final long serialVersionUID = -4938649324295079141L;
public Device() {
}
public Device(String ua, Integer dnt, Integer lmt, String ip, String ipv6, Integer devicetype, String make) {
this.ua = ua;
this.dnt = dnt;
this.ip = ip;
this.devicetype = devicetype;
}
@JsonProperty("ua")
public String getUa() {
return this.ua;
}
@JsonProperty("ua")
public void setUa(String ua) {
this.ua = ua;
}
@JsonProperty("dnt")
public Integer getDnt() {
return this.dnt;
}
@JsonProperty("dnt")
public void setDnt(Integer dnt) {
this.dnt = dnt;
}
@JsonProperty("ip")
public String getIp() {
return this.ip;
}
@JsonProperty("ip")
public void setIp(String ip) {
this.ip = ip;
}
@JsonProperty("devicetype")
public Integer getDevicetype() {
return this.devicetype;
}
@JsonProperty("devicetype")
public void setDevicetype(Integer devicetype) {
this.devicetype = devicetype;
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(Device.class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('[');
sb.append("ua");
sb.append('=');
sb.append(this.ua == null ? "<null>" : this.ua);
sb.append(',');
sb.append("dnt");
sb.append('=');
sb.append(this.dnt == null ? "<null>" : this.dnt);
sb.append(',');
sb.append("ip");
sb.append('=');
sb.append(this.ip == null ? "<null>" : this.ip);
sb.append(',');
sb.append("devicetype");
sb.append('=');
sb.append(this.devicetype == null ? "<null>" : this.devicetype);
sb.append(',');
sb.append("additionalProperties");
sb.append('=');
sb.append(this.additionalProperties == null ? "<null>" : this.additionalProperties);
sb.append(',');
if (sb.charAt(sb.length() - 1) == ',') {
sb.setCharAt(sb.length() - 1, ']');
} else {
sb.append(']');
}
return sb.toString();
}
public int hashCode() {
int result = 1;
result = result * 31 (this.ua == null ? 0 : this.ua.hashCode());
result = result * 31 (this.devicetype == null ? 0 : this.devicetype.hashCode());
result = result * 31 (this.ip == null ? 0 : this.ip.hashCode());
result = result * 31 (this.dnt == null ? 0 : this.dnt.hashCode());
return result;
}
public boolean equals(Object other) {
if (other == this) {
return true;
} else if (!(other instanceof Device)) {
return false;
} else {
Device rhs = (Device)other;
return (Objects.equals(this.ua, rhs.ua))
&& (Objects.equals(this.devicetype, rhs.devicetype) || this.devicetype != null
&& this.devicetype.equals(rhs.devicetype))
&& (Objects.equals(this.ip, rhs.ip))
&& (Objects.equals(this.dnt, rhs.dnt)) ;
}
}
}
下面是決議 json 的 java 代碼 -
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
public class DeviceJsonParserDemo {
public static void main(String[] args) throws IOException {
ObjectMapper jsonMapperBidRequest = new ObjectMapper();
String dev = Files.readString(Paths.get("src/main/resources/device.json"));
Device device = jsonMapperBidRequest.readValue(dev, Device.class);
System.out.println(device);
}
}
當您運行上面的代碼時,您將得到以下輸出 -
Device@5876a9af[ua=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36,dnt=<null>,ip=<null>,devicetype=<null>,additionalProperties={started=now, devtime=now}]
正如您在上面的輸出中注意到的那樣,不在 Device 類中的欄位位于 additionalProperties 欄位中。
現在我想將上述邏輯遷移到 typelevel circe
我有以下解碼
import io.circe.{Decoder, HCursor}
case class Device (ua: String, dnt: Option[Int], ip: Option[String], devicetype: Option[Int], addlProperties: Map[String, Any] = Map.empty)
object Device {
implicit val decodeFoo: Decoder[Device] = new Decoder[Device] {
final def apply(c: HCursor): Decoder.Result[Device] =
for {
ua <- c.downField("ua").as[String]
dnt <- c.downField("dnt").as[Option[Int]]
ip <- c.downField("ip").as[Option[String]]
devicetype <- c.downField("devicetype").as[Option[Int]]
} yield new Device(ua, dnt, ip, devicetype)
}
}
java決議邏輯是
import scala.io.Source
import io.circe.parser._
object DeviceJsonCirceDecodeDemo extends App {
val devString = Source.fromFile("src/main/resources/device.json").mkString
val device = decode[Device](devString)
println(device)
}
當我運行上面的代碼時,我得到以下輸出 -
Right(Device(Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36,None,None,None,Map()))
正如您在此處看到的,addlProperties地圖是空的,因為它沒有解碼器。
代碼在 github中用于 java 和 scala在這里我 怎樣才能在 circe 中實作相同的。
uj5u.com熱心網友回復:
一個相對簡單但有點難以維護的解決方案是將完整物件解碼為 Map 并洗掉已知鍵。
您的解碼器將變為:
implicit val decodeFoo: Decoder[Device] = Decoder.instance(c =>
for {
ua <- c.get[String]("ua")
dnt <- c.get[Option[Int]]("dnt")
ip <- c.get[Option[String]]("ip")
devicetype <- c.get[Option[Int]]("devicetype")
additional <- c.as[Map[String, Json]].map(_ - "ua" - "dnt" - "ip" - "devicetype")
} yield new Device(ua, dnt, ip, devicetype, additional)
)
我已經替換new Decoder為Decoder.instance和。這也假設是一個,您可能想要為一組特定型別定義一個解碼器。c.downField(...).as[...]c.get[...](...)addlPropertiesMap[String, Json]
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/459747.html
上一篇:嘗試將PureConfig和Circe用于scala時出現無形錯誤
下一篇:在元組中查找元素最小值的最佳方法
