Java 端:POJO → Jackson → JSON 字串 → 傳輸 (RabbitMQ/HTTP/TCP) → C# 端:JSON 字串 → Newtonsoft.Json → CLR 物件
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import java.io.IOException;
import java.util.Calendar;
public class NotifyMessage implements Serializable {
private static final ObjectMapper MAPPER = new ObjectMapper();
static {
// 統一時間格式:關鍵配置!
MAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
MAPPER.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
}
@JsonProperty("messageType")
private int type;
@JsonProperty("geoData")
private Object message; // 多型資料
@JsonProperty("time")
private Calendar time;
// Getters/Setters 略
public String toJson() throws IOException {
return MAPPER.writeValueAsString(this);
}
public static NotifyMessage fromJson(String json) throws IOException {
return json == null ? null : MAPPER.readValue(json, NotifyMessage.class);
}
}
using Newtonsoft.Json;
using System;
public class NotifyMessage
{
[JsonProperty("messageType")]
public int Type { get; set; }
[JsonProperty("geoData")]
public object Message { get; set; } // 對應 Java Object
[JsonProperty("time")]
public DateTime Time { get; set; } // 自動處理 ISO 8601 / 自訂格式
public string ToJson() => JsonConvert.SerializeObject(this, new JsonSerializerSettings
{
DateFormatString = "yyyy-MM-dd HH:mm:ss", // 與 Java 端一致
NullValueHandling = NullValueHandling.Ignore
});
public static NotifyMessage FromJson(string json)
{
return string.IsNullOrEmpty(json) ? null
: JsonConvert.DeserializeObject(json);
}
}
| 項目 | Java (Jackson) | C# (Newtonsoft.Json) | 說明 |
|---|---|---|---|
| 日期時間格式 | SimpleDateFormat("yyyy-MM-dd HH:mm:ss") | DateFormatString = "yyyy-MM-dd HH:mm:ss" | 雙邊必須一致,建議用 ISO 8601 (yyyy-MM-ddTHH:mm:ss) |
| 屬性命名 | @JsonProperty("camelCase") | [JsonProperty("camelCase")] | 統一用 camelCase,避免 PascalCase/camelCase 不匹配 |
| Null 處理 | 預設序列化 null | NullValueHandling.Ignore | 建議雙邊忽略 null 減少傳輸量 |
| 多型/Object | 需 @JsonTypeInfo 支援型別資訊 | TypeNameHandling.Auto | 若 geoData 為具體類別,需啟用型別標記 |
| Enum 序列化 | @JsonFormat(shape=JsonFormat.Shape.STRING) | StringEnumConverter | 序列化為字串而非數值 |
| 忽略未知屬性 | @JsonIgnoreProperties(ignoreUnknown=true) | MissingMemberHandling.Ignore | 版本演進相容性關鍵 |
// Java
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "@type")
@JsonSubTypes({
@JsonSubTypes.Type(value = Point.class, name = "Point"),
@JsonSubTypes.Type(value = Polygon.class, name = "Polygon")
})
public interface GeoData {}
public class Point implements GeoData {
public double x, y;
}
// C#
[JsonConverter(typeof(GeoDataConverter))] // 自訂 Converter 或用 TypeNameHandling
public interface IGeoData {}
public class Point : IGeoData {
public double X { get; set; }
public double Y { get; set; }
}
// 簡單做法:雙邊啟用 TypeNameHandling
var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto };
// Java: MAPPER.activateDefaultTyping(...)
[Obsolete] / @Deprecated,保留序列化相容性@JsonProperty("oldName") / [JsonProperty("oldName")]MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(obj)JsonConvert.SerializeObject(obj, Formatting.Indented)統一 JSON 契約、序列化配置、命名慣例與版本策略,是微服務異構語言互通的基石。Jackson 與 Newtonsoft.Json 皆為成熟庫,正確配置即可實現無縫互操作。