diff --git a/mavlink-bindgen/Cargo.toml b/mavlink-bindgen/Cargo.toml
index 2c23aeefaac642164116a901d7ed33451b2d4663..80fcbb71ba41f5a54ad0492ffe1263720476c686 100644
--- a/mavlink-bindgen/Cargo.toml
+++ b/mavlink-bindgen/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "mavlink-bindgen"
-version = "0.13.2"
+version = "0.14.0"
 edition.workspace = true
 license = "MIT/Apache-2.0"
 description = "Library used by rust-mavlink."
@@ -17,17 +17,29 @@ quote = "1"
 proc-macro2 = "1.0.43"
 lazy_static = "1.2.0"
 serde = { version = "1.0.115", optional = true, features = ["derive"] }
-clap = { version = "~4.3.24", optional = true, default-features =false, features = ["derive", "help", "usage", "error-context"] }
+clap = { version = "~4.3.24", optional = true, default-features = false, features = [
+    "derive",
+    "help",
+    "usage",
+    "error-context",
+] }
 thiserror = "1.0.56"
 
 # Required to support MSRV 1.65.0
-clap_lex = { version = "=0.5.0", optional=true }
-clap_builder = { version = "~4.3.24", optional=true}
-anstyle = { version = "=1.0.2", optional=true }
-anstyle-query = { version = "=1.0.0", optional=true }
-anstyle-parse = { version = "=0.2.1", optional=true }
+clap_lex = { version = "=0.5.0", optional = true }
+clap_builder = { version = "~4.3.24", optional = true }
+anstyle = { version = "=1.0.2", optional = true }
+anstyle-query = { version = "=1.0.0", optional = true }
+anstyle-parse = { version = "=0.2.1", optional = true }
 
 [features]
-cli = ["dep:clap", "dep:clap_lex", "dep:clap_builder", "dep:anstyle", "dep:anstyle-query", "dep:anstyle-parse"]
+cli = [
+    "dep:clap",
+    "dep:clap_lex",
+    "dep:clap_builder",
+    "dep:anstyle",
+    "dep:anstyle-query",
+    "dep:anstyle-parse",
+]
 emit-extensions = []
 emit-description = []
diff --git a/mavlink-bindgen/src/parser.rs b/mavlink-bindgen/src/parser.rs
index dce7263129824670660dcc195a8734b59ecce0d5..feebda8e6aceeb15a565ee5fa15c621855b6a26c 100644
--- a/mavlink-bindgen/src/parser.rs
+++ b/mavlink-bindgen/src/parser.rs
@@ -138,6 +138,7 @@ impl MavProfile {
         let mav_message_default_from_id =
             self.emit_mav_message_default_from_id(&enum_names, &struct_names);
         let mav_message_serialize = self.emit_mav_message_serialize(&enum_names);
+        let mav_message_get_field = self.emit_mav_message_get_field(&enum_names);
 
         quote! {
             #comment
@@ -152,6 +153,8 @@ impl MavProfile {
             #[allow(unused_imports)]
             use bitflags::bitflags;
 
+            use std::any::Any;
+
             use mavlink_core::{MavlinkVersion, Message, MessageData, bytes::Bytes, bytes_mut::BytesMut};
 
             #[cfg(feature = "serde")]
@@ -172,6 +175,7 @@ impl MavProfile {
                 #mav_message_default_from_id
                 #mav_message_serialize
                 #mav_message_crc
+                #mav_message_get_field
             }
         }
     }
@@ -279,6 +283,16 @@ impl MavProfile {
             }
         }
     }
+
+    fn emit_mav_message_get_field(&self, enums: &[TokenStream]) -> TokenStream {
+        quote! {
+            fn get_field(&self, index: usize) -> Option<Box<dyn Any>> {
+                match self {
+                    #(Self::#enums(body) => body.get_field(index),)*
+                }
+            }
+        }
+    }
 }
 
 #[derive(Debug, PartialEq, Eq, Clone, Default)]
@@ -565,6 +579,44 @@ impl MavMessage {
         }
     }
 
+    fn emit_get_field_impl(&self) -> TokenStream {
+        let field_names = self
+            .fields
+            .iter()
+            .enumerate()
+            .map(|(i, f)| {
+                let name = f.emit_name();
+                quote! {#i => Some(Box::new(self.#name)),}
+            })
+            .collect::<Vec<TokenStream>>();
+
+        let body = if field_names.is_empty() {
+            // struct has no fields
+            quote! {
+                None
+            }
+        } else {
+            quote! {
+                match index {
+                    #(#field_names)*
+                    _ => None,
+                }
+            }
+        };
+
+        let arg_name = if self.fields.is_empty() {
+            quote! {_index}
+        } else {
+            quote! {index}
+        };
+
+        quote! {
+            fn get_field(&self, #arg_name: usize) -> Option<Box<dyn Any>> {
+                #body
+            }
+        }
+    }
+
     fn emit_default_impl(&self) -> TokenStream {
         let msg_name = self.emit_struct_name();
         quote! {
@@ -595,6 +647,7 @@ impl MavMessage {
         let serialize_vars = self.emit_serialize_vars();
         let const_default = self.emit_const_default();
         let default_impl = self.emit_default_impl();
+        let get_field_impl = self.emit_get_field_impl();
 
         #[cfg(feature = "emit-description")]
         let description = self.emit_description();
@@ -632,6 +685,8 @@ impl MavMessage {
                 fn ser(&self, version: MavlinkVersion, bytes: &mut [u8]) -> usize {
                     #serialize_vars
                 }
+
+                #get_field_impl
             }
         }
     }
diff --git a/mavlink-core/src/lib.rs b/mavlink-core/src/lib.rs
index 0cc5e877853f34aba8089d2548080cce55ac1e6d..e06a985e5668b970c773a53744b9a8e556b0e7c6 100644
--- a/mavlink-core/src/lib.rs
+++ b/mavlink-core/src/lib.rs
@@ -23,7 +23,7 @@
 #![deny(clippy::all)]
 #![warn(clippy::use_self)]
 
-use core::result::Result;
+use core::{any::Any, result::Result};
 
 #[cfg(feature = "std")]
 use std::io::{Read, Write};
@@ -102,6 +102,7 @@ where
     fn message_id_from_name(name: &str) -> Result<u32, &'static str>;
     fn default_message_from_id(id: u32) -> Result<Self, &'static str>;
     fn extra_crc(id: u32) -> u8;
+    fn get_field(&self, index: usize) -> Option<Box<dyn Any>>;
 }
 
 pub trait MessageData: Sized {
@@ -114,6 +115,7 @@ pub trait MessageData: Sized {
 
     fn ser(&self, version: MavlinkVersion, payload: &mut [u8]) -> usize;
     fn deser(version: MavlinkVersion, payload: &[u8]) -> Result<Self, ParserError>;
+    fn get_field(&self, index: usize) -> Option<Box<dyn Any>>;
 }
 
 /// Metadata from a MAVLink packet header