Decimal fields conveyed as strings in the REST API #4863

Closed
opened 2025-12-29 19:21:21 +01:00 by adam · 6 comments
Owner

Originally created by @emersonfelipesp on GitHub (May 4, 2021).

Originally assigned to: @jeremystretch on GitHub.

NetBox version

v2.11.2

Python version

3.9

Steps to Reproduce

The HTTP GET response returns "vcpu" argument as string, but it should be a float, as requested on Issue #5975.

Steps to reproduce:

  1. Make HTTP GET request to /api/virtualization/virtual-machines/{id}/

HTTP GET Request

URI: https://demo.netbox.dev/api/virtualization/virtual-machines/543/

Headers:
Authorization: Token 977e9fb09fbfb2aa67ae06f90655b52edcee01e5
Host: demo.netbox.dev
User-Agent: PostmanRuntime/7.28.0
Accept: /
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Type: application/json

Expected Behavior

HTTP GET Response

{
    "id": 543,
    "url": "https://demo.netbox.dev/api/virtualization/virtual-machines/543/",
    "display": "vcpu is string, not float",
    "name": "vcpu is string, not float",
    "status": {
        "value": "active",
        "label": "Active"
    },
    "site": null,
    "cluster": {
        "id": 9,
        "url": "https://demo.netbox.dev/api/virtualization/clusters/9/",
        "display": "DO-AMS3",
        "name": "DO-AMS3"
    },
    "role": null,
    "tenant": null,
    "platform": null,
    "primary_ip": null,
    "primary_ip4": null,
    "primary_ip6": null,
    "vcpus": 10.00,
    "memory": 8196,
    "disk": 50,
    "comments": "",
    "local_context_data": null,
    "tags": [],
    "custom_fields": {},
    "config_context": {},
    "created": "2021-05-04",
    "last_updated": "2021-05-04T02:19:09.726988Z"
}

Observed Behavior

HTTP GET Response

{
    "id": 543,
    "url": "https://demo.netbox.dev/api/virtualization/virtual-machines/543/",
    "display": "vcpu is string, not float",
    "name": "vcpu is string, not float",
    "status": {
        "value": "active",
        "label": "Active"
    },
    "site": null,
    "cluster": {
        "id": 9,
        "url": "https://demo.netbox.dev/api/virtualization/clusters/9/",
        "display": "DO-AMS3",
        "name": "DO-AMS3"
    },
    "role": null,
    "tenant": null,
    "platform": null,
    "primary_ip": null,
    "primary_ip4": null,
    "primary_ip6": null,
    "vcpus": "10.00",
    "memory": 8196,
    "disk": 50,
    "comments": "",
    "local_context_data": null,
    "tags": [],
    "custom_fields": {},
    "config_context": {},
    "created": "2021-05-04",
    "last_updated": "2021-05-04T02:19:09.726988Z"
}
Originally created by @emersonfelipesp on GitHub (May 4, 2021). Originally assigned to: @jeremystretch on GitHub. ### NetBox version v2.11.2 ### Python version 3.9 ### Steps to Reproduce The HTTP GET response returns "vcpu" argument as **string**, but it should be a **float**, as requested on [Issue #5975](https://github.com/netbox-community/netbox/issues/5975). **Steps to reproduce:** 1. Make HTTP GET request to **/api/virtualization/virtual-machines/{id}/** --- ### HTTP GET Request **URI:** https://demo.netbox.dev/api/virtualization/virtual-machines/543/ **Headers:** Authorization: Token 977e9fb09fbfb2aa67ae06f90655b52edcee01e5 Host: demo.netbox.dev User-Agent: PostmanRuntime/7.28.0 Accept: */* Accept-Encoding: gzip, deflate, br Connection: keep-alive Content-Type: application/json ### Expected Behavior ### HTTP GET Response ``` { "id": 543, "url": "https://demo.netbox.dev/api/virtualization/virtual-machines/543/", "display": "vcpu is string, not float", "name": "vcpu is string, not float", "status": { "value": "active", "label": "Active" }, "site": null, "cluster": { "id": 9, "url": "https://demo.netbox.dev/api/virtualization/clusters/9/", "display": "DO-AMS3", "name": "DO-AMS3" }, "role": null, "tenant": null, "platform": null, "primary_ip": null, "primary_ip4": null, "primary_ip6": null, "vcpus": 10.00, "memory": 8196, "disk": 50, "comments": "", "local_context_data": null, "tags": [], "custom_fields": {}, "config_context": {}, "created": "2021-05-04", "last_updated": "2021-05-04T02:19:09.726988Z" } ``` ### Observed Behavior ### HTTP GET Response ``` { "id": 543, "url": "https://demo.netbox.dev/api/virtualization/virtual-machines/543/", "display": "vcpu is string, not float", "name": "vcpu is string, not float", "status": { "value": "active", "label": "Active" }, "site": null, "cluster": { "id": 9, "url": "https://demo.netbox.dev/api/virtualization/clusters/9/", "display": "DO-AMS3", "name": "DO-AMS3" }, "role": null, "tenant": null, "platform": null, "primary_ip": null, "primary_ip4": null, "primary_ip6": null, "vcpus": "10.00", "memory": 8196, "disk": 50, "comments": "", "local_context_data": null, "tags": [], "custom_fields": {}, "config_context": {}, "created": "2021-05-04", "last_updated": "2021-05-04T02:19:09.726988Z" } ```
adam added the type: bugstatus: accepted labels 2025-12-29 19:21:21 +01:00
adam closed this issue 2025-12-29 19:21:21 +01:00
Author
Owner

@jeremystretch commented on GitHub (May 4, 2021):

I'm not sure why these values are getting quoted. As far as I can tell the serializer field is defined correctly. Could be an issue with DRF itself.

>>> from virtualization.api.serializers import VirtualMachineSerializer
>>> VirtualMachineSerializer().fields['vcpus']
DecimalField(allow_null=True, decimal_places=2, label='VCPUs', max_digits=6, min_value=0.01, required=False)
@jeremystretch commented on GitHub (May 4, 2021): I'm not sure why these values are getting quoted. As far as I can tell the serializer field is defined correctly. Could be an issue with DRF itself. ``` >>> from virtualization.api.serializers import VirtualMachineSerializer >>> VirtualMachineSerializer().fields['vcpus'] DecimalField(allow_null=True, decimal_places=2, label='VCPUs', max_digits=6, min_value=0.01, required=False) ```
Author
Owner

@jeremystretch commented on GitHub (May 4, 2021):

Ok, yes, this seems to be intentional behavior by DRF: See the COERCE_DECIMAL_TO_STRING setting. (This issue also lends some context.) It seems to hinge on the difference between decimal and float types.

While I recognize that precision isn't likely a concern for this specific use case, I'm hesitant to deviate from the standard implementation. I can see this becoming quite muddy for values such as cable lengths.

@jeremystretch commented on GitHub (May 4, 2021): Ok, yes, this seems to be intentional behavior by DRF: See the [`COERCE_DECIMAL_TO_STRING`](https://www.django-rest-framework.org/api-guide/settings/#coerce_decimal_to_string) setting. ([This issue](https://github.com/encode/django-rest-framework/issues/2417) also lends some context.) It seems to hinge on the difference between decimal and float types. While I recognize that precision isn't likely a concern for this specific use case, I'm hesitant to deviate from the standard implementation. I can see this becoming quite muddy for values such as cable lengths.
Author
Owner

@jeremystretch commented on GitHub (May 4, 2021):

This also affects latitude and longitude on the dcim.Site model:

    "latitude": "12.345000",
    "longitude": "12.345000",
@jeremystretch commented on GitHub (May 4, 2021): This also affects `latitude` and `longitude` on the dcim.Site model: ``` "latitude": "12.345000", "longitude": "12.345000", ```
Author
Owner

@jeremystretch commented on GitHub (May 5, 2021):

I'm not sure it's fair to classify this as a bug, since it is technically intended behavior, though I do think we're okay to change it. Let's tag this for v2.12.

@jeremystretch commented on GitHub (May 5, 2021): I'm not sure it's fair to classify this as a bug, since it is technically intended behavior, though I do think we're okay to change it. Let's tag this for v2.12.
Author
Owner

@ziggekatten commented on GitHub (May 5, 2021):

In general, I have an opinion of never expect specific data types in responses. Given all APIs out there one thing that I have discovered is that you have to catch and format data anyway before processing. To be honest, life would be easier if everything was strings, and the processing of responses handle convversions.

But thats me, always encapsulating stuff in str(), int(), float() and so on...

@ziggekatten commented on GitHub (May 5, 2021): In general, I have an opinion of never expect specific data types in responses. Given all APIs out there one thing that I have discovered is that you have to catch and format data anyway before processing. To be honest, life would be easier if everything was strings, and the processing of responses handle convversions. But thats me, always encapsulating stuff in str(), int(), float() and so on...
Author
Owner

@emersonfelipesp commented on GitHub (May 6, 2021):

In general, I have an opinion of never expect specific data types in responses. Given all APIs out there one thing that I have discovered is that you have to catch and format data anyway before processing. To be honest, life would be easier if everything was strings, and the processing of responses handle convversions.

But thats me, always encapsulating stuff in str(), int(), float() and so on...

Although your opinion makes sense and I had to do exactly what you said, this specific behavior in Netbox is very different from the rest of the system, so would be great to make things working as expected, as the system is so consistent.

@emersonfelipesp commented on GitHub (May 6, 2021): > In general, I have an opinion of never expect specific data types in responses. Given all APIs out there one thing that I have discovered is that you have to catch and format data anyway before processing. To be honest, life would be easier if everything was strings, and the processing of responses handle convversions. > > But thats me, always encapsulating stuff in str(), int(), float() and so on... Although your opinion makes sense and I had to do exactly what you said, this specific behavior in Netbox is very different from the rest of the system, so would be great to make things working as expected, as the system is so consistent.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#4863