itsource

Json.NET의 부동/이중 소수점 이하(예: 용장 ".0" 없음)를 사용합니까?

mycopycode 2023. 3. 28. 21:46
반응형

Json.NET의 부동/이중 소수점 이하(예: 용장 ".0" 없음)를 사용합니까?

플로트와 더블을 연재할 때, Json.NET 에서는, 숫자에 프랙셔널 부분이 포함되지 않는 경우는, 항상 마지막에 「.0」을 추가합니다.좀 더 간결하게 표현할 수 있는 쉬운 방법이 없을까요?여러 숫자를 포함하는 개체를 직렬화할 때 추가 마침표와 0이 합산됩니다.

예를 들어, 이 코드를 실행하는 경우:

JsonConvert.SerializeObject(1.0);

저는 다음 결과를 기대하고 있습니다(또 희망합니다).

"1"

대신, 다음과 같은 것을 얻습니다.

"1.0"

소스 코드를 살펴보니 commit 0319263("...-fixed JsonConvert")에서 항상 소수점 자릿수를 쓰기 위해 의도적으로 추가된 것을 알 수 있었습니다.") 기본적으로 다음과 같은 코드를 실행합니다.

    private static string EnsureDecimalPlace(double value, string text)
    {
        if (double.IsNaN(value) || double.IsInfinity(value) ||
            text.IndexOf('.') != -1 || text.IndexOf('E') != -1 ||
            text.IndexOf('e') != -1)
        {
            return text;
        }

        return text + ".0";
    }

그래서 궁금해요.

  1. 그 변경의 이유는 무엇이었을까요?JSON 사양에서는 필요하지 않은 것 같습니다.

  2. 우회할 수 있는 쉬운 방법은 없나요?

질문 2에 대한 대체 답변으로, Json의 커스텀 버전을 컴파일하는 번거로움을 겪지 않는 것을 전제로 합니다.NET source) 독자적인 커스텀 JsonConverter 클래스를 생성하여 10진수, 부동값 및 이중값을 처리할 수 있습니다.사용하고 있는 버전은 다음과 같습니다.

    class DecimalJsonConverter : JsonConverter
    {
        public DecimalJsonConverter()
        {
        }

        public override bool CanRead
        {
            get
            {
                return false;
            }
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            throw new NotImplementedException("Unnecessary because CanRead is false. The type will skip the converter.");
        }

        public override bool CanConvert(Type objectType)
        {
            return (objectType == typeof(decimal) || objectType == typeof(float) || objectType == typeof(double));
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            if (DecimalJsonConverter.IsWholeValue(value))
            {
                writer.WriteRawValue(JsonConvert.ToString(Convert.ToInt64(value)));
            }
            else
            {
                writer.WriteRawValue(JsonConvert.ToString(value));
            }
        }

        private static bool IsWholeValue(object value)
        {
            if (value is decimal decimalValue)
            {
                int precision = (Decimal.GetBits(decimalValue)[3] >> 16) & 0x000000FF;
                return precision == 0;
            }
            else if (value is float floatValue)
            {
                return floatValue == Math.Truncate(floatValue);
            }
            else if (value is double doubleValue)
            {
                return doubleValue == Math.Truncate(doubleValue);
            }

            return false;
        }
    }

이렇게 하면 10진수 유형의 값에 대한 정밀도가 유지됩니다.10진수 값의 정밀도를 무시하는 경우 IsWholeValue() 함수의 10진수 부분을 플로트/더블 부분과 동일하게 사용할 수 있습니다.

        private static bool IsWholeValue(object value)
        {
            if (value is decimal decimalValue)
            {
                return decimalValue == Math.Truncate(decimalValue);
            }
            else if (value is float floatValue)
            {
                return floatValue == Math.Truncate(floatValue);
            }
            else if (value is double doubleValue)
            {
                return doubleValue == Math.Truncate(doubleValue);
            }

            return false;
        }

어느 경우든, 상기의 코드를 사용하려면 , 다음과 같이 시리얼 라이저를 호출합니다.

string json = JsonConvert.SerializeObject(value, new DecimalJsonConverter())

1. 그 변경의 이유는 무엇입니까?

사양은 필요없지만 금지할 수도 없습니다.

Json을 더 잘 확인할 수 있을 것 같아요.NET(어딘가에 NET이 있는 경우) 또는 정수형과 부동소수점 유형을 구분할 수 있는 "경우에 맞게"입니다.

Json.org 에서

2. 우회할 수 있는 쉬운 방법이 있나요?

그렇게 쉽진 않지만, 만약 당신이 정말로 원한다면, 당신만의 Json 버전을 다시 컴파일 할 수 있습니다.변경 후의 NETEnsureDecimalPlace()간단히 말하면return text;

언급URL : https://stackoverflow.com/questions/21153381/json-net-serializing-float-double-with-minimal-decimal-places-i-e-no-redundant

반응형