<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://mediawiki.wissen-ahrensburg.de/index.php?action=history&amp;feed=atom&amp;title=Rust-Datenmodell_f%C3%BCr_Drupal-Entities</id>
	<title>Rust-Datenmodell für Drupal-Entities - Versionsgeschichte</title>
	<link rel="self" type="application/atom+xml" href="https://mediawiki.wissen-ahrensburg.de/index.php?action=history&amp;feed=atom&amp;title=Rust-Datenmodell_f%C3%BCr_Drupal-Entities"/>
	<link rel="alternate" type="text/html" href="https://mediawiki.wissen-ahrensburg.de/index.php?title=Rust-Datenmodell_f%C3%BCr_Drupal-Entities&amp;action=history"/>
	<updated>2026-08-19T16:53:01Z</updated>
	<subtitle>Versionsgeschichte dieser Seite in Dokument</subtitle>
	<generator>MediaWiki 1.46.0</generator>
	<entry>
		<id>https://mediawiki.wissen-ahrensburg.de/index.php?title=Rust-Datenmodell_f%C3%BCr_Drupal-Entities&amp;diff=29&amp;oldid=prev</id>
		<title>Thorsten am 12. August 2026 um 10:40 Uhr</title>
		<link rel="alternate" type="text/html" href="https://mediawiki.wissen-ahrensburg.de/index.php?title=Rust-Datenmodell_f%C3%BCr_Drupal-Entities&amp;diff=29&amp;oldid=prev"/>
		<updated>2026-08-12T10:40:29Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw-interface=&quot;&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;de&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Nächstältere Version&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Version vom 12. August 2026, 10:40 Uhr&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l1&quot;&gt;Zeile 1:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Zeile 1:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== Übersicht ==&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== Übersicht ==&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l251&quot;&gt;Zeile 251:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Zeile 252:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[Kategorie:Rust]]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[Kategorie:Rust]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[Kategorie:Drupal]]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[Kategorie:Drupal]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;==Hinweis==&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Thorsten</name></author>
	</entry>
	<entry>
		<id>https://mediawiki.wissen-ahrensburg.de/index.php?title=Rust-Datenmodell_f%C3%BCr_Drupal-Entities&amp;diff=14&amp;oldid=prev</id>
		<title>Thorsten: Die Seite wurde neu angelegt: „== Übersicht ==  Dieser Artikel dokumentiert ein Rust-Datenmodell, das die zentralen Entity-Konzepte von Drupal (Node, User, Taxonomy Term, Media, Paragraph) als &lt;pre&gt;struct&lt;/pre&gt;/&lt;pre&gt;enum&lt;/pre&gt;-Typen abbildet. Das Modell enthält bewusst &#039;&#039;&#039;keine Logik&#039;&#039;&#039; (keine &lt;pre&gt;impl&lt;/pre&gt;-Methoden) – es dient als reine Datenrepräsentation. Eine (De-)Serialisierung (z. B. mit [https://serde.rs/ serde] für Drupal-JSON:API-Antworten) ist bewusst noch nicht Teil…“</title>
		<link rel="alternate" type="text/html" href="https://mediawiki.wissen-ahrensburg.de/index.php?title=Rust-Datenmodell_f%C3%BCr_Drupal-Entities&amp;diff=14&amp;oldid=prev"/>
		<updated>2026-08-12T01:20:46Z</updated>

		<summary type="html">&lt;p&gt;Die Seite wurde neu angelegt: „== Übersicht ==  Dieser Artikel dokumentiert ein Rust-Datenmodell, das die zentralen Entity-Konzepte von Drupal (Node, User, Taxonomy Term, Media, Paragraph) als &amp;lt;pre&amp;gt;struct&amp;lt;/pre&amp;gt;/&amp;lt;pre&amp;gt;enum&amp;lt;/pre&amp;gt;-Typen abbildet. Das Modell enthält bewusst &amp;#039;&amp;#039;&amp;#039;keine Logik&amp;#039;&amp;#039;&amp;#039; (keine &amp;lt;pre&amp;gt;impl&amp;lt;/pre&amp;gt;-Methoden) – es dient als reine Datenrepräsentation. Eine (De-)Serialisierung (z. B. mit [https://serde.rs/ serde] für Drupal-JSON:API-Antworten) ist bewusst noch nicht Teil…“&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Neue Seite&lt;/b&gt;&lt;/p&gt;&lt;div&gt;== Übersicht ==&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel dokumentiert ein Rust-Datenmodell, das die zentralen&lt;br /&gt;
Entity-Konzepte von Drupal (Node, User, Taxonomy Term, Media, Paragraph)&lt;br /&gt;
als &amp;lt;pre&amp;gt;struct&amp;lt;/pre&amp;gt;/&amp;lt;pre&amp;gt;enum&amp;lt;/pre&amp;gt;-Typen abbildet. Das Modell enthält bewusst &amp;#039;&amp;#039;&amp;#039;keine&lt;br /&gt;
Logik&amp;#039;&amp;#039;&amp;#039; (keine &amp;lt;pre&amp;gt;impl&amp;lt;/pre&amp;gt;-Methoden) – es dient als reine Datenrepräsentation.&lt;br /&gt;
Eine (De-)Serialisierung (z. B. mit [https://serde.rs/ serde] für&lt;br /&gt;
Drupal-JSON:API-Antworten) ist bewusst noch nicht Teil dieses Modells&lt;br /&gt;
und folgt in einem späteren Schritt.&lt;br /&gt;
&lt;br /&gt;
== Motivation ==&lt;br /&gt;
&lt;br /&gt;
Drupal modelliert Inhalte über ein generisches Entity-System:&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Entity-Typen&amp;#039;&amp;#039;&amp;#039; (&amp;lt;pre&amp;gt;node&amp;lt;/pre&amp;gt;, &amp;lt;pre&amp;gt;user&amp;lt;/pre&amp;gt;, &amp;lt;pre&amp;gt;taxonomy_term&amp;lt;/pre&amp;gt;, &amp;lt;pre&amp;gt;media&amp;lt;/pre&amp;gt;, …) definieren die grundlegende Art eines Objekts.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Bundles&amp;#039;&amp;#039;&amp;#039; (bei Nodes „Content Types&amp;quot; genannt, z. B. &amp;lt;pre&amp;gt;article&amp;lt;/pre&amp;gt;, &amp;lt;pre&amp;gt;page&amp;lt;/pre&amp;gt;) spezialisieren einen Entity-Typ.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Felder&amp;#039;&amp;#039;&amp;#039; (&amp;lt;pre&amp;gt;field_*&amp;lt;/pre&amp;gt;) sind pro Bundle konfigurierbar, typisiert und können einfach- oder mehrwertig (Kardinalität) sein.&lt;br /&gt;
&lt;br /&gt;
Um mit einem Drupal-Backend aus Rust heraus zu arbeiten, braucht man&lt;br /&gt;
typisierte Gegenstücke zu diesen Konzepten. Das hier beschriebene&lt;br /&gt;
Modell bildet diese Struktur 1:1 in Rust ab.&lt;br /&gt;
&lt;br /&gt;
== Grundtypen ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#[derive(Debug, Clone, PartialEq, Eq)]&lt;br /&gt;
pub enum EntityType {&lt;br /&gt;
    Node,&lt;br /&gt;
    User,&lt;br /&gt;
    TaxonomyTerm,&lt;br /&gt;
    Media,&lt;br /&gt;
    Paragraph,&lt;br /&gt;
    File,&lt;br /&gt;
    Menu,&lt;br /&gt;
    Block,&lt;br /&gt;
    Custom(String),&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]&lt;br /&gt;
pub enum PublishStatus {&lt;br /&gt;
    Published,&lt;br /&gt;
    Unpublished,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
pub type LangCode = String;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;EntityType&amp;lt;/pre&amp;gt; bildet die von Drupal vordefinierten Entity-Typen ab; der&lt;br /&gt;
&amp;lt;pre&amp;gt;Custom&amp;lt;/pre&amp;gt;-Zweig deckt eigene, per Modul definierte Entity-Typen ab, ohne&lt;br /&gt;
das Enum ändern zu müssen.&lt;br /&gt;
&lt;br /&gt;
== Feldwerte: &amp;lt;pre&amp;gt;FieldValue&amp;lt;/pre&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Drupal-Felder sind stark typisiert (Text, Zahl, Datum, Referenz, Bild, …).&lt;br /&gt;
Dies wird über ein Enum mit Payload pro Variante abgebildet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#[derive(Debug, Clone)]&lt;br /&gt;
pub enum FieldValue {&lt;br /&gt;
    Text(String),&lt;br /&gt;
    TextLong { value: String, format: Option&amp;lt;String&amp;gt; },&lt;br /&gt;
    Integer(i64),&lt;br /&gt;
    Decimal(f64),&lt;br /&gt;
    Boolean(bool),&lt;br /&gt;
    DateTime(DateTime&amp;lt;Utc&amp;gt;),&lt;br /&gt;
    Email(String),&lt;br /&gt;
    Link { uri: String, title: Option&amp;lt;String&amp;gt; },&lt;br /&gt;
    EntityReference { target_id: u64, target_type: EntityType },&lt;br /&gt;
    Image {&lt;br /&gt;
        target_id: u64,&lt;br /&gt;
        alt: Option&amp;lt;String&amp;gt;,&lt;br /&gt;
        title: Option&amp;lt;String&amp;gt;,&lt;br /&gt;
        width: Option&amp;lt;u32&amp;gt;,&lt;br /&gt;
        height: Option&amp;lt;u32&amp;gt;,&lt;br /&gt;
    },&lt;br /&gt;
    List(Vec&amp;lt;FieldValue&amp;gt;),&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
pub type FieldMap = HashMap&amp;lt;String, FieldValue&amp;gt;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;pre&amp;gt;List(Vec&amp;lt;FieldValue&amp;gt;)&amp;lt;/pre&amp;gt; bildet mehrwertige Felder ab (Kardinalität &amp;gt; 1).&lt;br /&gt;
* &amp;lt;pre&amp;gt;FieldMap&amp;lt;/pre&amp;gt; ist die generische Ablage für alle &amp;lt;pre&amp;gt;field_*&amp;lt;/pre&amp;gt;-Werte eines Bundles, adressiert über den Feldmaschinennamen (z. B. &amp;lt;pre&amp;gt;field_tags&amp;lt;/pre&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
== Entity-Typen im Detail ==&lt;br /&gt;
&lt;br /&gt;
=== Gemeinsame Basis ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#[derive(Debug, Clone)]&lt;br /&gt;
pub struct EntityBase {&lt;br /&gt;
    pub id: u64,&lt;br /&gt;
    pub uuid: Uuid,&lt;br /&gt;
    pub entity_type: EntityType,&lt;br /&gt;
    pub bundle: String,&lt;br /&gt;
    pub langcode: LangCode,&lt;br /&gt;
    pub created: DateTime&amp;lt;Utc&amp;gt;,&lt;br /&gt;
    pub changed: DateTime&amp;lt;Utc&amp;gt;,&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;EntityBase&amp;lt;/pre&amp;gt; fasst Eigenschaften zusammen, die praktisch jede&lt;br /&gt;
Content-Entity in Drupal besitzt, und wird per Komposition in konkrete&lt;br /&gt;
Entity-Structs eingebettet (siehe &amp;lt;pre&amp;gt;Node&amp;lt;/pre&amp;gt;, &amp;lt;pre&amp;gt;Media&amp;lt;/pre&amp;gt;). Beim späteren&lt;br /&gt;
Ergänzen von serde bietet sich dafür &amp;lt;pre&amp;gt;#[serde(flatten)]&amp;lt;/pre&amp;gt; an, damit die&lt;br /&gt;
Felder von &amp;lt;pre&amp;gt;EntityBase&amp;lt;/pre&amp;gt; beim (De-)Serialisieren auf derselben Ebene&lt;br /&gt;
wie die restlichen Felder erscheinen.&lt;br /&gt;
&lt;br /&gt;
=== Node ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#[derive(Debug, Clone)]&lt;br /&gt;
pub struct Node {&lt;br /&gt;
    pub base: EntityBase,&lt;br /&gt;
    pub title: String,&lt;br /&gt;
    pub status: PublishStatus,&lt;br /&gt;
    pub author_id: u64,&lt;br /&gt;
    pub fields: FieldMap,&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== User ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#[derive(Debug, Clone)]&lt;br /&gt;
pub struct User {&lt;br /&gt;
    pub id: u64,&lt;br /&gt;
    pub uuid: Uuid,&lt;br /&gt;
    pub name: String,&lt;br /&gt;
    pub mail: String,&lt;br /&gt;
    pub status: bool,&lt;br /&gt;
    pub roles: Vec&amp;lt;String&amp;gt;,&lt;br /&gt;
    pub created: DateTime&amp;lt;Utc&amp;gt;,&lt;br /&gt;
    pub fields: FieldMap,&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;User&amp;lt;/pre&amp;gt; nutzt bewusst kein &amp;lt;pre&amp;gt;EntityBase&amp;lt;/pre&amp;gt;, da User-Entities in Drupal kein&lt;br /&gt;
&amp;lt;pre&amp;gt;bundle&amp;lt;/pre&amp;gt;/&amp;lt;pre&amp;gt;langcode&amp;lt;/pre&amp;gt; im klassischen Sinn besitzen und stattdessen&lt;br /&gt;
&amp;lt;pre&amp;gt;roles&amp;lt;/pre&amp;gt; und einen einfachen &amp;lt;pre&amp;gt;status: bool&amp;lt;/pre&amp;gt; (aktiv/blockiert) haben.&lt;br /&gt;
&lt;br /&gt;
=== TaxonomyTerm ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#[derive(Debug, Clone)]&lt;br /&gt;
pub struct TaxonomyTerm {&lt;br /&gt;
    pub id: u64,&lt;br /&gt;
    pub uuid: Uuid,&lt;br /&gt;
    pub vocabulary: String,&lt;br /&gt;
    pub name: String,&lt;br /&gt;
    pub description: Option&amp;lt;String&amp;gt;,&lt;br /&gt;
    pub parent_id: Option&amp;lt;u64&amp;gt;,&lt;br /&gt;
    pub weight: i32,&lt;br /&gt;
    pub fields: FieldMap,&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bildet Taxonomiebegriffe inkl. hierarchischer Eltern-Referenz&lt;br /&gt;
(&amp;lt;pre&amp;gt;parent_id&amp;lt;/pre&amp;gt;) und Sortiergewicht (&amp;lt;pre&amp;gt;weight&amp;lt;/pre&amp;gt;) ab.&lt;br /&gt;
&lt;br /&gt;
=== Media &amp;amp; Paragraph ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#[derive(Debug, Clone)]&lt;br /&gt;
pub struct Media {&lt;br /&gt;
    pub base: EntityBase,&lt;br /&gt;
    pub name: String,&lt;br /&gt;
    pub fields: FieldMap,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#[derive(Debug, Clone)]&lt;br /&gt;
pub struct Paragraph {&lt;br /&gt;
    pub id: u64,&lt;br /&gt;
    pub uuid: Uuid,&lt;br /&gt;
    pub bundle: String,&lt;br /&gt;
    pub fields: FieldMap,&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Paragraph&amp;lt;/pre&amp;gt; ist bewusst schlank gehalten, da Paragraphs in Drupal keine&lt;br /&gt;
eigenständigen, direkt aufrufbaren Entities mit URL/Alias sind, sondern&lt;br /&gt;
stets über eine Host-Entity referenziert werden.&lt;br /&gt;
&lt;br /&gt;
== Schema-Introspektion (optional) ==&lt;br /&gt;
&lt;br /&gt;
Für Anwendungsfälle, in denen Feld- und Bundle-Definitionen selbst&lt;br /&gt;
(nicht nur Werte) abgebildet werden müssen – etwa um ein Drupal-Schema&lt;br /&gt;
zu spiegeln oder Formulare dynamisch zu generieren:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]&lt;br /&gt;
pub enum Cardinality {&lt;br /&gt;
    Single,&lt;br /&gt;
    Multiple,&lt;br /&gt;
    Unlimited,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#[derive(Debug, Clone)]&lt;br /&gt;
pub struct FieldDefinition {&lt;br /&gt;
    pub field_name: String,&lt;br /&gt;
    pub field_type: String,&lt;br /&gt;
    pub cardinality: Cardinality,&lt;br /&gt;
    pub required: bool,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#[derive(Debug, Clone)]&lt;br /&gt;
pub struct BundleDefinition {&lt;br /&gt;
    pub entity_type: EntityType,&lt;br /&gt;
    pub bundle: String,&lt;br /&gt;
    pub label: String,&lt;br /&gt;
    pub fields: Vec&amp;lt;FieldDefinition&amp;gt;,&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Design-Entscheidungen ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Entscheidung !! Begründung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;pre&amp;gt;FieldValue&amp;lt;/pre&amp;gt; als Enum mit Payload pro Variante || Bildet Drupals starke Feldtypisierung typsicher ab, statt alles als &amp;lt;pre&amp;gt;String&amp;lt;/pre&amp;gt; zu behandeln.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;pre&amp;gt;FieldMap = HashMap&amp;lt;String, FieldValue&amp;gt;&amp;lt;/pre&amp;gt; || Bundles sind zur Compile-Zeit nicht bekannt; generische Map bleibt flexibel für beliebige &amp;lt;pre&amp;gt;field_*&amp;lt;/pre&amp;gt;-Namen.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;pre&amp;gt;EntityBase&amp;lt;/pre&amp;gt; als Kompositionsfeld || Vermeidet Duplikation gemeinsamer Properties zwischen Node/Media, ohne Vererbung (die es in Rust nicht gibt).&lt;br /&gt;
|-&lt;br /&gt;
| Kein &amp;lt;pre&amp;gt;impl&amp;lt;/pre&amp;gt;-Block || Modell bleibt reine Datenschicht; Geschäftslogik (Validierung, API-Calls) gehört in separate Module.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;pre&amp;gt;EntityType::Custom(String)&amp;lt;/pre&amp;gt; || Deckt durch Contrib-/Custom-Module definierte Entity-Typen ab, ohne das Enum erweitern zu müssen.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Offene Erweiterungspunkte ==&lt;br /&gt;
&lt;br /&gt;
* Weitere &amp;lt;pre&amp;gt;FieldValue&amp;lt;/pre&amp;gt;-Varianten je nach genutzten Feldtypen (z. B. &amp;lt;pre&amp;gt;Geolocation&amp;lt;/pre&amp;gt;, &amp;lt;pre&amp;gt;Address&amp;lt;/pre&amp;gt;, &amp;lt;pre&amp;gt;File&amp;lt;/pre&amp;gt; losgelöst von &amp;lt;pre&amp;gt;Image&amp;lt;/pre&amp;gt;).&lt;br /&gt;
* Übersetzungen (&amp;lt;pre&amp;gt;translations: HashMap&amp;lt;LangCode, FieldMap&amp;gt;&amp;lt;/pre&amp;gt;), falls Drupal-Mehrsprachigkeit (Content Translation) abgebildet werden soll.&lt;br /&gt;
* Konkretes Mapping auf die JSON:API-Hüllstruktur (&amp;lt;pre&amp;gt;data&amp;lt;/pre&amp;gt;, &amp;lt;pre&amp;gt;attributes&amp;lt;/pre&amp;gt;, &amp;lt;pre&amp;gt;relationships&amp;lt;/pre&amp;gt;, &amp;lt;pre&amp;gt;included&amp;lt;/pre&amp;gt;), falls direkt gegen die Drupal-JSON:API deserialisiert werden soll, statt ein eigenes flaches Modell zu pflegen.&lt;br /&gt;
&lt;br /&gt;
== Verwendete Crates ==&lt;br /&gt;
&lt;br /&gt;
* [https://crates.io/crates/chrono chrono] – Zeitstempel (&amp;lt;pre&amp;gt;created&amp;lt;/pre&amp;gt;, &amp;lt;pre&amp;gt;changed&amp;lt;/pre&amp;gt;)&lt;br /&gt;
* [https://crates.io/crates/uuid uuid] – Entity-UUIDs&lt;br /&gt;
&lt;br /&gt;
Hinweis: [https://serde.rs/ serde] (für die (De-)Serialisierung) ist&lt;br /&gt;
bewusst noch nicht Teil dieses Modells und wird in einem späteren&lt;br /&gt;
Schritt ergänzt.&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* Drupal-Dokumentation: [https://www.drupal.org/docs/drupal-apis/entity-api Entity API]&lt;br /&gt;
* Drupal-Dokumentation: [https://www.drupal.org/docs/core-modules-and-themes/core-modules/jsonapi-module JSON:API-Modul]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Rust]]&lt;br /&gt;
[[Kategorie:Drupal]]&lt;/div&gt;</summary>
		<author><name>Thorsten</name></author>
	</entry>
</feed>