Date Time을 사용할 수 있는 이유MinValue가 UTC보다 이전 시간대로 일련화되지 않았습니까?
WCF REST 서비스에 문제가 있습니다.반환하려는 와이어 오브젝트에 특정 속성이 설정되어 있지 않아 Date Time이 됩니다.DateTime 유형의 속성에 대한 최소값입니다.서비스가 빈 문서(HTTP 상태 200 ?)를 반환합니다.?) JSON 시리얼라이제이션에 직접 콜을 걸려고 하면 다음과 같은 예외가 발생합니다.
시리얼화예외:Date Time 값보다 큰 Date Time 값.최대값 또는 DateTime보다 작습니다.UTC로 변환된 MinValue는 JSON으로 직렬화할 수 없습니다.
콘솔 앱에서 다음 코드를 실행하여 이를 재현할 수 있습니다.
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(DateTime));
MemoryStream m = new MemoryStream();
DateTime dt = DateTime.MinValue;
// throws SerializationException in my timezone
ser.WriteObject(m, dt);
string json = Encoding.ASCII.GetString(m.GetBuffer());
Console.WriteLine(json);
왜 이런 행동일까요?제 시간대(GMT+1)와 관련이 있다고 생각합니다.Date Time(날짜 시간)으로.MinValue는 디폴트(DateTime)이므로 문제없이 시리얼화할 수 있을 것으로 예상됩니다.
REST 서비스를 어떻게 동작시킬지 조언해 주시겠어요?데이터 계약을 변경하고 싶지 않습니다.
가장 큰 문제는DateTime.MinValue
가지다DateTimeKind.Unspecified
다음과 같이 정의됩니다.
MinValue = new DateTime(0L, DateTimeKind.Unspecified);
그러나 이것은 실제 문제가 아닙니다.이 정의는 시리얼라이제이션 중 문제로 이어집니다.JSON Date Time 시리얼화는 다음 방법으로 이루어집니다.
System.Runtime.Serialization.Json.JsonWriterDelegator.WriteDateTime(DateTime value)
유감스럽게도 다음과 같이 정의됩니다.
...
if (value.Kind != DateTimeKind.Utc)
{
long num = value.Ticks - TimeZone.CurrentTimeZone.GetUtcOffset(value).Ticks;
if ((num > DateTime.MaxValue.Ticks) || (num < DateTime.MinValue.Ticks))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString("JsonDateTimeOutOfRange"), new ArgumentOutOfRangeException("value")));
}
}
...
그래서 그것은 고려되지 않는다.Unspecified
라고 취급합니다.Local
. 이 상황을 피하기 위해 자체 상수를 정의할 수 있습니다.
MinValueUtc = new DateTime(0L, DateTimeKind.Utc);
또는
MinValueUtc = DateTime.MinValue.ToUniversalTime();
물론 이상하게 보이긴 하지만 도움이 될 거야
임의의 DateTime 멤버에 이 추가 시도
[DataMember(IsRequired = false, EmitDefaultValue = false)]
이러한 에러의 대부분은 디폴트값이datetime
이DateTime.MinValue
JSON의 연재는 1970년부터입니다.
표준시가 GMT+1인 경우 UTC 값은DateTime.MinValue
당신의 타임존에서 당신의 타임존은DateTime.MinValue
.
이 생성자를 사용합니다.
public DataContractJsonSerializer(Type type, IEnumerable<Type> knownTypes, int maxItemsInObjectGraph, bool ignoreExtensionDataObject, IDataContractSurrogate dataContractSurrogate, bool alwaysEmitTypeInformation)
코드 예:
DataContractJsonSerializer serializer = new DataContractJsonSerializer(o.GetType(), null, int.MaxValue, false, new DateTimeSurrogate(), false);
public class DateTimeSurrogate : IDataContractSurrogate
{
#region IDataContractSurrogate 成员
public object GetCustomDataToExport(Type clrType, Type dataContractType)
{
return null;
}
public object GetCustomDataToExport(System.Reflection.MemberInfo memberInfo, Type dataContractType)
{
return null;
}
public Type GetDataContractType(Type type)
{
return type;
}
public object GetDeserializedObject(object obj, Type targetType)
{
return obj;
}
public void GetKnownCustomDataTypes(System.Collections.ObjectModel.Collection<Type> customDataTypes)
{
}
public object GetObjectToSerialize(object obj, Type targetType)
{
if (obj.GetType() == typeof(DateTime))
{
DateTime dt = (DateTime)obj;
if (dt == DateTime.MinValue)
{
dt = DateTime.MinValue.ToUniversalTime();
return dt;
}
return dt;
}
if (obj == null)
{
return null;
}
var q = from p in obj.GetType().GetProperties()
where (p.PropertyType == typeof(DateTime)) && (DateTime)p.GetValue(obj, null) == DateTime.MinValue
select p;
q.ToList().ForEach(p =>
{
p.SetValue(obj, DateTime.MinValue.ToUniversalTime(), null);
});
return obj;
}
public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData)
{
return null;
}
public System.CodeDom.CodeTypeDeclaration ProcessImportedType(System.CodeDom.CodeTypeDeclaration typeDeclaration, System.CodeDom.CodeCompileUnit compileUnit)
{
return typeDeclaration;
}
#endregion
}
보다 우아한 방법은 Date Time 필드의 기본값을 내보내지 않도록 시리얼라이저에 지시하는 것이라고 생각합니다.이렇게 하면 전송 중에 바이트를 절약하고 값이 없는 필드를 직렬화할 때 바이트를 절약할 수 있습니다.예:
[DataContract]
public class Document {
[DataMember]
public string Title { get; set; }
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public DateTime Modified { get; set; }
}
또는 Nullables를 사용할 수 있습니다.예:
[DataContract]
public class Document {
[DataMember]
public string Title { get; set; }
[DataMember]
public DateTime? Modified { get; set; }
}
이 모든 것은 프로젝트에서 사용할 수 있는 요건과 제한에 따라 달라집니다.데이터 유형만 변경할 수 없는 경우도 있습니다.이 경우에도 여전히 이 서비스를 이용할 수 있습니다.DataMember
속성을 지정하고 데이터 유형을 그대로 유지합니다.
에서는 in음음음음음음이 있는 new Document() { Title = "Test Document" }
에 , 「JSON」이 .{"Title": "Test Document"}
따라서 자바스크립트나 다른 클라이언트에서도 쉽게 처리할 수 있습니다.JSON(JSON)입니다.을 하고 돌아오게 됩니다.undefined
. 으로 예상되는에 따라 입력된 언어에서는 유형(일반적으로 예상되는 동작)에 따라 해당 속성의 기본값이 지정됩니다.
library.GetDocument(id).success(function(raw){
var document = JSON.Parse(raw);
var date = document.date; // date will be *undefined*
...
}
OnSerializing Atribut과 리플렉션을 통해 시리얼라이제이션 중에 수정할 수 있습니다.
[OnSerializing]
public void OnSerializing(StreamingContext context)
{
var properties = this.GetType().GetProperties();
foreach (PropertyInfo property in properties)
{
if (property.PropertyType == typeof(DateTime) && property.GetValue(this).Equals(DateTime.MinValue))
{
property.SetValue(this, DateTime.MinValue.ToUniversalTime());
}
}
}
사용자 지정 DateTimeFormat을 지정하면(WriteDateTimeInDefaultFormat 메서드를 사용하여) 문제를 방지할 수 있습니다.
DataContractJsonSerializerSettings settings = new DataContractJsonSerializerSettings();
settings.DateTimeFormat = new DateTimeFormat("yyyy-MM-ddThh:mm:ss.fffZ");
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(MyDataContract), settings);
DateTime 값이 실제로 UTC 내에 있는지 확인해야 하지만 DateTime과 함께 사용해도 안전합니다.최소값
사용하고 있는 DateTimeFormat 의 상세한 것에 대하여는, 이것을 참조해 주세요.
언급URL : https://stackoverflow.com/questions/4025851/why-can-datetime-minvalue-not-be-serialized-in-timezones-ahead-of-utc
'programing' 카테고리의 다른 글
선택 목록의 출력을 부모 목록에 종속시키려면 어떻게 해야 합니까? (0) | 2023.02.18 |
---|---|
Jackson Json Type Info 。As.EXTERNAL_PROPERTY가 예상대로 작동하지 않습니다. (0) | 2023.02.15 |
각도에서의 ScrollTo 함수JS (0) | 2023.02.15 |
TypeError:scrollIntoView는 함수가 아닙니다. (0) | 2023.02.15 |
Meteor는 어떤 보안 장치를 가지고 있나요? (0) | 2023.02.15 |