serde
serde copied to clipboard
cannot deserialize IPv6 SocketAddr from Strings
i just switched to serde - previously I was parsing configs with IPv6 addresses manually and calling to_socket_addrs
directly.
i noticed that it's not possible to automatically parse IPv6 addresses when deserializing String fields, and I needed to write a manual deserialize_with
and convert to a String first. things seem to work as expected with IPv4 addresses.
example:
use std::net::{SocketAddr, ToSocketAddrs};
use serde::Deserialize;
#[derive(Debug, Clone, Deserialize)]
struct Config {
address: SocketAddr
}
fn main() {
// prints "address: [::1]:8080"
println!("address: {}", "::1:8080".to_socket_addrs().unwrap().next().unwrap());
let s = "{\"address\": \"::1:8080\"}";
// this line fails with:
// thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error("invalid IP address syntax", line: 1, column: 22)', src/main.rs:17:40
serde_json::from_str::<Config>(&s).unwrap();
}
@cfal FWIW [::1]:8080
parses as you'd expect. ::1:8080
is a valid IPv6 address, so many parsers need brackets to disambiguate these cases.
@olix0r oh interesting! thanks for the tip. i was curious if it'd work with a 5-digit port number (since i think that wouldn't be a valid ipv6 address anymore?), but it does still raise an error.
it might actually be fine to always require the square brackets for my usecase. i haven't looked at the serde code, but still curious to me why it works directly with String, i had expected the same behavior.
This behavior is consistent with the standard library's impl FromStr for SocketAddr
.
@cfal brackets in IPv6 with port or within an URL are mandatory per IETF RFC to distinguish address, port and how many last octets you want to define.
E.g. ::1
is the same as 0:0:0:0:0:0:0:1
and ::1:8080
is 0:0:0:0:0:0:1:8080
per IPv6 RFC