Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Number type (u16) field of struct throwing "invalid type: floating point 21010, expected u16" #425

Closed
EliHarper opened this issue Aug 17, 2023 · 2 comments
Assignees
Labels

Comments

@EliHarper
Copy link

Versions/Environment

  1. What version of Rust are you using?
    1.71.1

  2. What operating system are you using?
    Ubuntu 22.04.3 LTS x86_64

  3. What versions of the driver and its dependencies are you using? (Run
    cargo pkgid mongodb & cargo pkgid bson)
    mongodb@2.6.1
    bson@2.6.1

  4. What version of MongoDB are you using? (Check with the MongoDB shell using db.version())
    6.0.6

  5. What is your MongoDB topology (standalone, replica set, sharded cluster, serverless)?
    replica set

Describe the bug

A u16 (port) field in a struct throws a deserialization error claiming that 21010 is a floating point number, rather than a u16.

Deserialization is triggered with a mongodb::cursor like it is performed in the mongodb docs.rs find example:

// Iterate over the results of the cursor.
while let Some(book) = cursor.try_next().await? {
    println!("title: {}", book.title);
}

I expected it to deserialize the struct with the u16 primitive type without issue.

  • If you know how to reproduce this bug, please include a code snippet here:
#[derive(Debug, Serialize, Deserialize)]
struct Book {
    title: String,
    author: String,
    problem: u16,
}

...

// Query the books in the collection with a filter and an option.
let filter = doc! { "author": "George Orwell" };
let find_options = FindOptions::builder().sort(doc! { "title": 1 }).build();
let mut cursor = typed_collection.find(filter, find_options).await?;

// Iterate over the results of the cursor.
while let Some(book) = cursor.try_next().await? { # DeserializationError
    println!("title: {}", book.title);
}
@abr-egn
Copy link
Contributor

abr-egn commented Aug 18, 2023

Hi!

I can't reproduce the issue you're seeing. This test program

use bson::doc;
use mongodb::options::FindOptions;
use serde::{Serialize, Deserialize};
use futures::stream::TryStreamExt;

#[derive(Debug, Serialize, Deserialize)]
struct Book {
    title: String,
    author: String,
    problem: u16,
}

#[tokio::main]
async fn main() {
    let book = Book {
        title: "1984".to_string(),
        author: "George Orwell".to_string(),
        problem: 21010,
    };
    println!("original book:    {:?}", book);
    let bson_roundtrip: Book = bson::from_bson(bson::to_bson(&book).unwrap()).unwrap();
    println!("bson roundtrip:   {:?}", bson_roundtrip);
    let binary_roundtrip: Book = bson::from_reader(bson::to_vec(&book).unwrap().as_slice()).unwrap();
    println!("binary roundtrip: {:?}", binary_roundtrip);

    let client = mongodb::Client::with_uri_str("mongodb://localhost:27017").await.unwrap();
    let typed_collection = client.database("test_u16").collection::<Book>("test");
    typed_collection.drop(None).await.unwrap();
    typed_collection.insert_one(&book, None).await.unwrap();

    // Query the books in the collection with a filter and an option.
    let filter = doc! { "author": "George Orwell" };
    let find_options = FindOptions::builder().sort(doc! { "title": 1 }).build();
    let mut cursor = typed_collection.find(filter, find_options).await.unwrap();

    // Iterate over the results of the cursor.
    while let Some(book) = cursor.try_next().await.unwrap() {
        println!("title: {}", book.title);
    }
}

executes and prints

original book:    Book { title: "1984", author: "George Orwell", problem: 21010 }
bson roundtrip:   Book { title: "1984", author: "George Orwell", problem: 21010 }
binary roundtrip: Book { title: "1984", author: "George Orwell", problem: 21010 }
title: 1984

Please note that BSON, unlike JSON, distinguishes between integer and floating-point values; is it possible that the data you're trying to retrieve has this field stored as a float?

@EliHarper
Copy link
Author

You're right! I apologize for the oversight.
Thanks so much for getting back to me!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants