Serde is a framework for serializing and deserializing Rust data structures efficiently and generically.

Overview

Serde   Build Status Latest Version serde: rustc 1.13+ serde_derive: rustc 1.31+

Serde is a framework for serializing and deserializing Rust data structures efficiently and generically.


You may be looking for:

Serde in action

Click to show Cargo.toml. Run this code in the playground.
[dependencies]

# The core APIs, including the Serialize and Deserialize traits. Always
# required when using Serde. The "derive" feature is only required when
# using #[derive(Serialize, Deserialize)] to make Serde work with structs
# and enums defined in your crate.
serde = { version = "1.0", features = ["derive"] }

# Each data format lives in its own crate; the sample code below uses JSON
# but you may be using a different one.
serde_json = "1.0"

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug)]
struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let point = Point { x: 1, y: 2 };

    // Convert the Point to a JSON string.
    let serialized = serde_json::to_string(&point).unwrap();

    // Prints serialized = {"x":1,"y":2}
    println!("serialized = {}", serialized);

    // Convert the JSON string back to a Point.
    let deserialized: Point = serde_json::from_str(&serialized).unwrap();

    // Prints deserialized = Point { x: 1, y: 2 }
    println!("deserialized = {:?}", deserialized);
}

Getting help

Serde is one of the most widely used Rust libraries so any place that Rustaceans congregate will be able to help you out. For chat, consider trying the #general or #beginners channels of the unofficial community Discord, the #rust-usage channel of the official Rust Project Discord, or the #general stream in Zulip. For asynchronous, consider the [rust] tag on StackOverflow, the /r/rust subreddit which has a pinned weekly easy questions post, or the Rust Discourse forum. It's acceptable to file a support issue in this repo but they tend not to get as many eyes as any of the above and may get closed without a response after some time.


License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Serde by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Comments
  • Xml

    Xml

    would you be so kind as to review the serde_macros and Deserializer changes?

    current state:

    • [x] xml to struct deserialization
    • [x] deserialize bool, int, string from <anytagname>value</anythingelse>
    • [x] deserialize sequences (tuple, array, vector) as struct member
    • [x] deserialize escaped chars (&abcd;)
    • [x] deserialize CDATA
    • [ ] deserialize enumerations
    • [ ] deserialize arrays of enumerations
    • [ ] deserialize errors instead of assertions
    • [ ] more deserialize tests
    • [x] parse to dom tree
    • [ ] remove debug print! messages
    • [ ] struct to xml serialization

    anti-features (just ignoring stuff I don't like):

    • [x] ignore namespaces
    • [x] skip xml comments
    • [x] skip xml version tag
    • [x] ignoring xml-attributes

    things that would be nice to have but might not be possible

    • [ ] xsd verification
    • [ ] sequences of sequences (how would these even look like in xml?)
    • [ ] attributes to collapse xml elements that only contain a single type of element.
    opened by oli-obk 53
  • Flatten

    Flatten

    I am interacting with an API which returns pagination information on most of their requests. Here is an example:

    {
        "limit": 25,
        "offset": 0,
        "total": 1,
        "users": [
            {...}
        ]
    }
    

    limit, offset, and total are present for many of the responses received. Here is the struct I deserialize the JSON response into:

    #[derive(Debug, Serialize, Deserialize)]
    pub struct Users {
        limit: i32,
        offset: i32,
        total: i32,
        users: Vec<User>
    }
    

    The problem that I'm having is that I don't know how I can avoid repeating those same 3 fields in other structs.

    I would like to have something similar to this:

    #[derive(Debug, Serialize, Deserialize)]
    pub struct Pagination {
        offset: i32,
        limit: i32,
        total: i32
    }
    
    #[derive(Debug, Serialize, Deserialize)]
    pub struct Users {
        pagination: Pagination,
        users: Vec<User>
    }
    

    Here serde would see that no field pagination was present but the type of the struct field is Pagination which contains fields which are present in the response.

    I guess this could be solved with some kind of struct inheritance but Rust doesn't have that at the moment which restricts us to use composition.

    Any ideas?

    enhancement derive 
    opened by arnm 40
  • Helper library of useful de/serialize_with functions

    Helper library of useful de/serialize_with functions

    For example the ones from https://github.com/serde-rs/serde/issues/550 and https://github.com/serde-rs/serde-rs.github.io/issues/22. These don't need to be in serde itself but if there are ones that people ask for over and over, we can stick those in a helper crate and provide a better out-of-the-box experience compared to "implement your own serialize_with" or "paste this code into your project."

    discussion 
    opened by dtolnay 32
  • (De)serialization of enums could use a simpler format

    (De)serialization of enums could use a simpler format

    I have worked only with serde_json, to I may be missing something that applies to other (de)serializers.

    Serialization

    Serialization of enums seems to always produce objects, even for trivial constructors

    #[derive(Serialize, Deserialize)]
    pub enum Foo {
        A, B, C
    }
    
    fn main() {
      println!("{}", serde_json::to_string(&Foo::A).unwrap());
      // prints: `{"A":[]}`
    }
    

    This produces {"A":[]}. I would prefer if it produced just the string "A".

    Deserialization

    More importantly, deserialization of enums seems to always require objects, which is annoying when one attempts to implement a protocol.

    #[derive(Serialize, Deserialize)]
    pub enum Foo {
        A, B, C
    }
    
    fn main() {
      let a : Foo = self::serde_json::from_str("\"A\"").unwrap();
      // panics with a syntax error
    }
    

    I would have preferred if it managed to deserialize the string "A" into enum constructor A.

    edit Fixed typo in the second example.

    enhancement 
    opened by Yoric 32
  • Rc<> gets deserialized incorrectly

    Rc<> gets deserialized incorrectly

    The way serde currently treats ref-counted data structures means that it creates copies of the references objects. This is bad for several reasons:

    • Potentially increased memory usage
    • Equality comparison that relies on comparison of address breaks
    • Interior mutability is not reflected in copies and maybe more that I can't think of right away. I think there should at least be big warnings in the documentation about this behaviour, but the support should be either fixed or deprecated, imo.
    breaking change 
    opened by shahn 31
  • Decide whether Syntex bumps require a Serde major version change

    Decide whether Syntex bumps require a Serde major version change

    @alexcrichton https://github.com/serde-rs/serde/pull/346#issuecomment-223723712

    Changes like this which update syntex, a public dependency of serde_codegen (e.g. it reexports types from syntex) are actually a breaking change for the serde crate. Could this be signaled with a major version update or holding off the upgrade? This unfortunately breaks any other crate which is depending on serde_codegen as it may get a mismatch of syntex versions otherwise.

    We're probably damned either way. If Serde were on version 0.33, the 275 crates that depend on Serde would be fragmented across all of them (about half are still on ^0.6) and would not work together.

    On the one hand (no major version change), we occasionally break crates that use a ^ dependency on Serde and also have another dependency on Syntex. Where this is unacceptable, you could use an = dependency.

    On the other hand, we would never break ^ dependencies but practically every time you do cargo update you would end up in a broken state until 275 crates synchronize their Serde dependency.

    logistics 
    opened by dtolnay 29
  • Capture other unrecognized fields

    Capture other unrecognized fields

    #[derive(Serialize, Deserialize)]
    struct S {
        a: u32,
        b: String,
        #[serde(other)]
        other: Map<String, Value>,
    }
    
    {"a":0,"b":"","c":true}
    

    This would deserialize into other containing "c" => true.

    enhancement derive 
    opened by dtolnay 28
  • more flexible JSON serialization

    more flexible JSON serialization

    Serialization for machines

    When structures are serialized to JSON to be transferred over the wire, there may be servers that expect null values to be omitted, possibly to save bandwidth. Right now, there is no way in serde to omit null values.

    As a practical example, imagine someone trying to upload a video to youtube:

    $ youtube3 --debug videos insert \
    -r snippet \
    title="Google APIs for Rust: Developer Diary #2 [Making CLIs]" \
    description="TBD" \
    tags="Google APIs, Google, rust-lang, Diary, OSS" \
    category-id=22 \
    ..status privacy-status=private \
    embeddable=true \
    license=youtube \
    -u resumable ~/Movies/youtube-originals/Google\ APIs\ for\ Rust\ -\ Using\ youtube3\ to\ upload\ a\ video.mov application/octet-stream
    

    Which yields the following error:

    Bad Requst (400): Invalid value for: null is not a valid value
    

    As well as the following dialogue between client and server:

    POST /resumable/upload/youtube/v3/videos?part=status%2Csnippet&alt=json&uploadType=resumable HTTP/1.1
    User-Agent: google-api-rust-client/0.1.6
    Host: www.googleapis.com
    Transfer-Encoding: chunked
    Content-Type: application/json
    X-Upload-Content-Type: application/octet-stream
    Authorization: Bearer ya29.YwHqwwVjMrn7y_qO7d6RR5KeowbDJFO_2mLk5pTPs9iJZP0k3DEHUm6E4xkOv3pw5oEhX3GBjI-H4A
    
    33C
    {"status":{"license":"youtube","embeddable":true,"privacyStatus":"private","publishAt":null,"publicStatsViewable":null,"uploadStatus":null,"rejectionReason":null,"failureReason":null},"topicDetails":null,"monetizationDetails":null,"suggestions":null,"ageGating":null,"fileDetails":null,"player":null,"id":null,"localizations":null,"liveStreamingDetails":null,"snippet":{"description":"TBD","tags":["Google APIs, Google, rust-lang, Diary, OSS"],"channelId":null,"defaultLanguage":null,"liveBroadcastContent":null,"publishedAt":null,"thumbnails":null,"title":"Google APIs for Rust: Developer Diary #2 [Making CLIs]","categoryId":"22","localized":null,"channelTitle":null},"kind":null,"statistics":null,"projectDetails":null,"conversionPings":null,"processingDetails":null,"etag":null,"contentDetails":null,"recordingDetails":null}
    0
    
    HTTP/1.1 400 Bad Request
    Vary: Origin
    Vary: X-Origin
    Content-Type: application/json; charset=UTF-8
    Content-Length: 234
    Date: Tue, 28 Apr 2015 06:31:59 GMT
    Server: UploadServer ("Built on Apr 20 2015 22:37:13 (1429594633)")
    Alternate-Protocol: 443:quic,p=1
    
    {
     "error": {
      "errors": [
       {
        "domain": "global",
        "reason": "invalid",
        "message": "Invalid value for: null is not a valid value"
       }
      ],
      "code": 400,
      "message": "Invalid value for: null is not a valid value"
     }
    }
    

    As you can see, the request contains null values which are not allowed.

    To further stress the importance of this feature, have a look at the respective Go implementation ...

    type AccessPolicy struct {
        // Allowed: The value of allowed indicates whether the access to the
        // policy is allowed or denied by default.
        Allowed bool `json:"allowed,omitempty"`
    
        // Exception: A list of region codes that identify countries where the
        // default policy do not apply.
        Exception []string `json:"exception,omitempty"`
    }
    

    ... where the marker omitempty will prevent it to be serialized if unset.

    You can try it yourself using the youtube3 program, which can be downloaded here.

    Serialization for human consumption

    Right now there is exactly one method to get 'pretty', i.e. more human-friendly json output. It provides no option to specify how exactly that could be done.

    The most prominent one to me would be a setting for whether or not to ignore null values. Other options could be the indentation string to use, e.g. \t or .

    Motivation

    When printing the server response of any of the various google apis using a generated command-line interface, simple invocation yield results like this:

    $ discovery1 apis get-rest discovery v1
    {
      "protocol": "rest",
      "methods": null,
      "labels": null,
      "kind": "discovery#restDescription",
      "canonicalName": null,
      "ownerName": "Google",
      "documentationLink": "https://developers.google.com/discovery/",
      "auth": null,
      "packagePath": null,
      "batchPath": "batch",
      "id": "discovery:v1",
      "features": null,
      "ownerDomain": "google.com",
      "rootUrl": "https://www.googleapis.com/",
      "name": "discovery",
      "parameters": {
        "key": {
          "description": "API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.",
          "format": null,
          "enum": null,
          "variant": null,
          "enumDescriptions": null,
          "readOnly": null,
          "minimum": null,
          "repeated": null,
          "id": null,
          "$ref": null,
          "default": null,
          "items": null,
          "required": null,
          "maximum": null,
          "properties": null,
          "location": "query",
          "pattern": null,
          "additionalProperties": null,
          "type": "string",
          "annotations": null
        },
        "userIp": {
          "description": "IP address of the site where the request originates. Use this if you want to enforce per-user limits.",
          "format": null,
          "enum": null,
          "variant": null,
          "enumDescriptions": null,
          "readOnly": null,
          "minimum": null,
          "repeated": null,
          "id": null,
          "$ref": null,
          "default": null,
          "items": null,
          "required": null,
          "maximum": null,
          "properties": null,
          "location": "query",
          "pattern": null,
          "additionalProperties": null,
          "type": "string",
          "annotations": null
        },
      [...]
      "revision": null
    }
    

    The above should look like this:

    $ discovery1 apis get-rest discovery v1
    {
     "kind": "discovery#restDescription",
     "etag": "\"ye6orv2F-1npMW3u9suM3a7C5Bo/rJ-Wlqqs_yJDjtCFAIylPtmqXPY\"",
     "discoveryVersion": "v1",
     "id": "discovery:v1",
     "name": "discovery",
     "version": "v1",
     "title": "APIs Discovery Service",
     "description": "Lets you discover information about other Google APIs, such as what APIs are available, the resource and method details for each API.",
     "ownerDomain": "google.com",
     "ownerName": "Google",
     "icons": {
      "x16": "http://www.google.com/images/icons/feature/filing_cabinet_search-g16.png",
      "x32": "http://www.google.com/images/icons/feature/filing_cabinet_search-g32.png"
     },
     "documentationLink": "https://developers.google.com/discovery/",
     "protocol": "rest",
     "baseUrl": "https://www.googleapis.com/discovery/v1/",
     "basePath": "/discovery/v1/",
     "rootUrl": "https://www.googleapis.com/",
     "servicePath": "discovery/v1/",
     "batchPath": "batch",
     "parameters": {
      "alt": {
       "type": "string",
       "description": "Data format for the response.",
       "default": "json",
       "enum": [
        "json"
       ],
       "enumDescriptions": [
        "Responses with Content-Type of application/json"
       ],
       "location": "query"
      },
      "fields": {
       "type": "string",
       "description": "Selector specifying which fields to include in a partial response.",
       "location": "query"
      },
      "key": {
       "type": "string",
       "description": "API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.",
       "location": "query"
      },
      "oauth_token": {
       "type": "string",
       "description": "OAuth 2.0 token for the current user.",
       "location": "query"
      },
      "prettyPrint": {
       "type": "boolean",
       "description": "Returns response with indentations and line breaks.",
       "default": "true",
       "location": "query"
      },
      "quotaUser": {
       "type": "string",
       "description": "Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters. Overrides userIp if both are provided.",
       "location": "query"
      },
      "userIp": {
       "type": "string",
       "description": "IP address of the site where the request originates. Use this if you want to enforce per-user limits.",
       "location": "query"
      }
     },
     "schemas": {
      "DirectoryList": {
       "id": "DirectoryList",
       "type": "object",
       "properties": {
        "discoveryVersion": {
         "type": "string",
         "description": "Indicate the version of the Discovery API used to generate this doc.",
         "default": "v1"
        },
        "items": {
         "type": "array",
         "description": "The individual directory entries. One entry per api/version pair.",
         "items": {
          "type": "object",
          "properties": {
           "description": {
            "type": "string",
            "description": "The description of this API."
           },
           "discoveryLink": {
            "type": "string",
            "description": "A link to the discovery document."
           },
           "discoveryRestUrl": {
            "type": "string",
            "description": "The URL for the discovery REST document."
           },
           "documentationLink": {
            "type": "string",
            "description": "A link to human readable documentation for the API."
           },
           "icons": {
            "type": "object",
            "description": "Links to 16x16 and 32x32 icons representing the API.",
            "properties": {
             "x16": {
              "type": "string",
              "description": "The URL of the 16x16 icon."
             },
             "x32": {
              "type": "string",
              "description": "The URL of the 32x32 icon."
             }
            }
           },
           "id": {
            "type": "string",
            "description": "The id of this API."
           },
           "kind": {
            "type": "string",
            "description": "The kind for this response.",
            "default": "discovery#directoryItem"
           },
           "labels": {
            "type": "array",
            "description": "Labels for the status of this API, such as labs or deprecated.",
            "items": {
             "type": "string"
            }
           },
           "name": {
            "type": "string",
            "description": "The name of the API."
           },
           "preferred": {
            "type": "boolean",
            "description": "True if this version is the preferred version to use."
           },
           "title": {
            "type": "string",
            "description": "The title of this API."
           },
           "version": {
            "type": "string",
            "description": "The version of the API."
           }
          }
         }
        },
        "kind": {
         "type": "string",
         "description": "The kind for this response.",
         "default": "discovery#directoryList"
        }
       }
      },
     [...]
    }
    
    enhancement 
    opened by Byron 28
  • Implementing custom type serializing

    Implementing custom type serializing

    I'm trying to implement custom type serializer for the BigInt type. So, the first thing that I've made is a look into the serde docs. But this case a little bit complex, that described inside the doc.

    That's a code, which I'm using for a serializing:

    use num::bigint::{BigInt, Sign};  // other crate
    use serde::ser;
    
    pub struct Serializer<W>{
        writer: W
    }
    
    impl<W> ser::Serializer for Serializer<W> where W: io::Write {
      // some code there...
    }
    
    impl ser::Serialize for BigInt {
        fn serialize<S>(&self, serializer: &mut S) -> Result<()> where S: Serializer {
            let (sign, bytes) = *self.to_bytes_le();
            let length = bytes.len();
            match length {
                0...255 => self.get_small_big_number(sign, length as u8, bytes),
                _ => self.get_large_big_number(sign, length as u32, bytes),
            }
        }
    }
    

    As a result, the complier generates an error:

    src/serializers.rs:591:71: 591:81 error: `Serializer` is not a trait [E0404]
    src/serializers.rs:591     fn serialize<S>(&self, serializer: &mut S) -> Result<()> where S: Serializer {
                                                                                                 ^~~~~~~~~~
    src/serializers.rs:591:71: 591:81 help: run `rustc --explain E0404` to see a detailed explanation
    error: cannot continue compilation due to previous error
    error: Could not compile `bert`.
    

    How can I connect all this stuff together and provide method to serialize BigInt type? I've also trying to implement serializing for BigInt type from the num crate as described there, but getting the same error as I said earlier.

    support 
    opened by Relrin 25
  • Add codegen expr magic for default, skip serializing, and alternative serializers

    Add codegen expr magic for default, skip serializing, and alternative serializers

    This is an alternative implementation of #214, #198, #208 and implements #90 and #216. This allows one to write:

    #[derive(Serialize, Deserialize)]
    struct Struct {
        #[serde(default="123")]
        a: i32,
        #[serde(skip_serializing_if="self.b == 123")]
        b: i32,
        #[serde(serialize_with="(self.b == 123).serialize(serializer)"]
        c: i32,
        #[serde(deserialize_with="Ok(if try!(bool::deserialize(deserializer) { 123) } else { 0 })"]
        d: i32,
    }
    

    cc @oli-obk, @target-san, @arcnmx

    opened by erickt 25
  • Implemented disallow_unknown

    Implemented disallow_unknown

    • Added codegen for disallow_unknown
    • ... with new default to ignore unknown values during deserialization
    • Added ContainerAttrs

    Original pull request against v0.6.x: https://github.com/serde-rs/serde/pull/201

    opened by JohnHeitmann 24
  • derive macro error for wrong style of attribute syntax is misleading

    derive macro error for wrong style of attribute syntax is misleading

    #[derive(Debug, Serialize, Deserialize)]
    pub struct Config {
        download: PathBuf,
        #[serde(skip_serializing_if(Option::is_none))]
        storage: Option<PathBuf>,
        upload: bool,
    }
    

    The above code will cause the following compiler error:

    error: unknown serde field attribute `skip_serializing_if`
      --> src/main.rs:10:13
       |
    10 |     #[serde(skip_serializing_if(Option::is_none))]
       |             ^^^^^^^^^^^^^^^^^^^
    

    however, there is a field attribute skip_serializing_if.

    It would be more helpful to recognize the wrong syntax and suggest the correct syntax instead:

    error: expected key = value syntax, e.g. `skip_serializing_if = "..."`
      --> src/main.rs:10:13
       |
    10 |     #[serde(skip_serializing_if(Option::is_none))]
       |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    

    I expect this will be painstaking due to the number of possible serde attributes, but the result is possible in theory.

    I'd like to take a stab at implementing it if you're happy with the stated goal. I've done similar for much simpler and smaller) proc macros of my own in the past.

    If not, no worries. It might make serde slightly slower to compile anyway for what is only a minor papercut for beginners (or muppets such as myself) :)

    opened by drmason13 0
  • Question about serde_derive with no_std

    Question about serde_derive with no_std

    #666 mentions that serde_derive already supports no_std, but I found serde_derive unconditionally dependent on proc_macro2, which use std.
    According to rust-lang/rust#38509 it will get compiled anyway.
    So I am confused can it really works in an environment without std? (eg. Linux kernel with Rust) Will it fail at runtime?

    opened by avalon1610 0
  • Skip serialization on None on a per record basis

    Skip serialization on None on a per record basis

    Is it possible to optionally skip serialization?

    Say I have a db query that is select * where I want all values to be serialized whether there is data or not vs a db query that specifies what I want selected where I only want to serialize the values that are not None...

    I don't know if #[serde(skip_serializing_if = "Option::is_none")] is flexible enough for this case..

    Maybe something like...

    #[derive(Serialize, Deserialize)]
    struct SomeStruct {
      value: Option<Value>
    }
    
    let mut val = SomeStruct::new();
    val.skip_serialization(Option::is_none);
    
    opened by letto4135 0
  • derive_ser: Fix `clippy::use_self` on enum

    derive_ser: Fix `clippy::use_self` on enum

    opened by finga 0
  • Can serde support `crate-type` `dylib`?

    Can serde support `crate-type` `dylib`?

    This might be a bit of a long shot, but I thought I would ask :)

    Dynamically linking crates can improve the incremental compilation time of projects substantially. serde, as a dependency that can increase compilation times quite a bit, would be a good target to make dynamic.

    Since serde is usually used in combination with crates that implement specific serialization formats such as serde_json it'll normally be added as a dependency by both the final user and the crate implementing the serialization format like serde_json.

    When wrapping both serde and serde_json as dylibs to improve compilation speed, we end up with a situation like

      graph TD;
          bin["binary"]-.->serde_dylib["serde (dylib)"];
          bin-.->serde_json_dylib["serde_json (dylib)"];
          serde_json_dylib-->serde_json;
          serde_json-->serde1["serde"];
          serde_dylib-->serde2["serde"];
    

    Since serde does not specify crate-type dylib it'll need to be linked statically by both serde_json and the dynamic serde wrapper. This is something that is not supported by Rust: https://github.com/rust-lang/rust/issues/34909#issuecomment-274643453. We basically run into the diamond dependency problem, where two static copies of serde end up in the dependency graph and Rust errors with error: cannot satisfy dependencies so serde only shows up once as it cannot decide which copy to use. This is also explained in the module comment of rust/compiler/rustc_metadata/src/dependency_format.rs.

    A solution to the problem would be to allow dynamic linking against serde by adding

    [lib]
    crate-type = ["rlib", "dylib"]
    

    to serde/Cargo.toml. This would let consumers of the crate allow to opt-in to dynamic linking, basically allowing for a dependency graph like

      graph TD;
          bin["binary"]-.->serde["serde (dylib)"];
          bin-.->serde_json_dylib["serde_json (dylib)"];
          serde_json_dylib-->serde_json;
          serde_json-.->serde;
    

    This would not change how serde is linked if crates do not require dynamic linking as static linking is the default (see dependency_format.rs). So this should be a backwards compatible change. Only if serde is used like in the initial example, this would allow it to be used as a dylib. RUSTFLAGS="-C prefer-dynamic" would have the same effect.

    This issue has been raised here originally.

    I'm aware of the importance of serde and know that such a change cannot be done lightly. So if this is asking too much, feel free to close. On the other hand, I think it would have quite a positive impact on incremental compilation time and is worth bringing up.

    opened by rksm 2
  • Differing behaviour of `serializer.serialize_bool()` when using `#[serde(serialize_with =

    Differing behaviour of `serializer.serialize_bool()` when using `#[serde(serialize_with = "...")]`

    I have an enum which I am serializing using serde and serde_json so that some of the variants are of String type, and others are bool:

    enum Filter {
        Text,
        True,
    }
    

    I can manually implement Serialize like this, which works for my use case:

    impl Serialize for Filter {
        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where
            S: Serializer,
        {
            match *self {
                Self::Text => serializer.serialize_str("text"),
                Self::True => serializer.serialize_bool(true),
            }
        }
    }
    

    However, I have lots of these sorts of enums and I don't want to pay the cost of manually serializing all of the String cases every time I want one or two variants to be bool. So, I can up with this:

    #[derive(Serialize)]
    #[serde(rename_all = "lowercase")]
    pub enum Filter {
        Text,
        #[serde(serialize_with = "serialize_true")]
        True,
    }
    
    fn serialize_true<S>(serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_bool(true)
    }
    

    The problem now is that Filter::True serializes (in json) to Object({"true": true}), whereas with the manual impl, it serializes to just a plain true.

    I tried adding #[serde(untagged)] to the enum, but whilst that fixes theboolcase, theStringcases now get serialized tonull`!

    Is this expected behaviour that calling serializer.serialize_bool() has a different output when called from a serialize_with context versus a manual impl context?

    If this is better in the serde_json issue tracker, let me know...

    opened by mfreeborn 0
Releases(v1.0.145)
  • v1.0.145(Sep 22, 2022)

  • v1.0.144(Aug 21, 2022)

    • Change atomic ordering used by Serialize impl of atomic types to match ordering used by Debug impl of those same types (#2263, thanks @taiki-e)
    Source code(tar.gz)
    Source code(zip)
  • v1.0.143(Aug 9, 2022)

  • v1.0.142(Aug 3, 2022)

  • v1.0.141(Aug 1, 2022)

  • v1.0.140(Jul 20, 2022)

  • v1.0.139(Jul 11, 2022)

  • v1.0.138(Jul 2, 2022)

  • v1.0.137(May 1, 2022)

    • Update documentation links to some data formats whose repos have moved (#2201, thanks @atouchet)
    • Fix declared rust-version of serde and serde_test (#2168)
    Source code(tar.gz)
    Source code(zip)
  • v1.0.136(Jan 25, 2022)

  • v1.0.135(Jan 25, 2022)

  • v1.0.134(Jan 21, 2022)

  • v1.0.133(Jan 1, 2022)

  • v1.0.132(Dec 16, 2021)

  • v1.0.131(Dec 9, 2021)

  • v1.0.130(Aug 28, 2021)

  • v1.0.129(Aug 28, 2021)

  • v1.0.128(Aug 21, 2021)

  • v1.0.127(Jul 31, 2021)

  • v1.0.126(May 12, 2021)

  • v1.0.125(Mar 22, 2021)

  • v1.0.124(Mar 6, 2021)

  • v1.0.123(Jan 25, 2021)

    • Support Self keywords in fields of types that derive Deserialize (#1830, thanks @taiki-e)
    • Allow floats to be deserialized from ints in tagged unions (#1842, thanks @Timmmm)
    • Support Self inside fields that use serialize_with (#1970)
    Source code(tar.gz)
    Source code(zip)
  • v1.0.122(Jan 25, 2021)

    • Add IntoDeserializer impl for &[u8] (#1898, thanks @Mingun)

    • Handle unrecognized numeric field keys during deserialization of a field_identifier, equivalently to string field keys (#1914, thanks @Mingun)

    • Add attribute to override default deserialization failure expectation message (#1916, thanks @Mingun)

      #[derive(Deserialize)]
      #[serde(untagged, expecting = "single version or array of versions")]
      struct VersionSpec {
          One(Version),
          Many(Vec<Version>),
      }
      
    • Improve serde_test handling of map entries and error message construction (#1918, thanks @Mingun)

    • Produce more accurate location information on test failures from serde_test crate (#1920, thanks @Mingun)

    • Improve diagnostic on failure to parse a rename_all attribute (#1960, #1961)

    • Eliminate unnecessary trait bounds on some value Deserializer impls (#1963)

    Source code(tar.gz)
    Source code(zip)
  • v1.0.121(Jan 23, 2021)

    • Support borrowed data during deserialization of a field identifier (#1917, thanks @Mingun)
    • Fix panic when deserializing Duration with nanoseconds that cause the seconds counter to overflow (#1958, thanks @jonasbb)
    Source code(tar.gz)
    Source code(zip)
  • v1.0.120(Jan 19, 2021)

  • v1.0.118(Dec 5, 2020)

  • v1.0.117(Oct 15, 2020)

  • v1.0.116(Sep 11, 2020)

    • Fix deserialization of IpAddr, SocketAddr, Bound, Result, OsString in formats which process variant identifiers as u64 (#1888, thanks @joshtriplett)
    Source code(tar.gz)
    Source code(zip)
  • v1.0.115(Aug 10, 2020)

Coding-challenge - Algorithms and Data-structures, problems and solutions in Rust language using cargo-workspaces

Coding Challenge LeetCode/Hackerrank e.t.c Using this as an opportunity to improve my knowledge of rust lang If you found this repo useful to you, add

Tolumide Shopein 17 Apr 24, 2022
Algorithms and Data Structures of all kinds written in Rust.

Classic Algorithms in Rust This repo contains the implementation of various classic algorithms for educational purposes in Rust. Right now, it is in i

Alexander González 37 Sep 8, 2022
Common data structures and algorithms in Rust

Contest Algorithms in Rust A collection of classic data structures and algorithms, emphasizing usability, beauty and clarity over full generality. As

Aram Ebtekar 3.2k Sep 26, 2022
Rust data structures and client for the PubChem REST API

pubchem.rs Rust data structures and client for the PubChem REST API. ?? Usage ?? Compound Create a Compound to query the PubChem API for a single comp

Martin Larralde 2 Jan 18, 2022
Rust Persistent Data Structures

Rust Persistent Data Structures Rust Persistent Data Structures provides fully persistent data structures with structural sharing. Setup To use rpds a

Diogo Sousa 849 Sep 19, 2022
A proof of concept implementation of cyclic data structures in stable, safe, Rust.

A proof of concept implementation of cyclic data structures in stable, safe, Rust. This demonstrates the combined power of the static-rc crate and the

null 155 Sep 19, 2022
Rust library for string parsing of basic data structures.

afmt Simple rust library for parsing basic data structures from strings. Usage You can specify string formats to any strucute, via the use of the fmt

Eduard 4 May 8, 2021
Library containing various Data Structures implemented using Rust.

rust-data-structures Library containing various Data Structures implemented using Rust. Running You can test the library by running cargo test, an exa

c1m50c 1 Jan 6, 2022
A library for comparing data structures in Rust, oriented toward testing

Delta: Structural differencing in Rust The delta crate defines the trait Delta, along with a derive macro for auto-generating instances of this trait

John Wiegley 14 Mar 7, 2022
A library for comparing data structures in Rust, oriented toward testing

The comparable crate defines the trait [Comparable], along with a derive macro for auto-generating instances of this trait for most data types. Primar

John Wiegley 14 Mar 7, 2022
Collection of Data Structures in Rust

cds - Collection of Data Structures !!! UNDER CONSTRUCTION !!! The version v0.0.1 is a crates.io placeholder. License Licensed under either of Apache

Rafael Buchbinder 2 May 23, 2022
Succinct data structures in Rust

sucds: Succinct data structures in Rust sucds contains some succinct data structures written in Rust. Data structures So far, the following data struc

Shunsuke Kanda 38 Jul 9, 2022
Dade is data definition for Rust structures.

dade dade is data definition for Rust structures. For the easy handle of data, the following will support it. Data validation. Data schema conforms Js

odd 3 May 1, 2022
NixEl is a Rust library that turns Nix code into a variety of correct, typed, memory-safe data-structures

?? NixEL Lexer, Parser, Abstract Syntax Tree and Concrete Syntax Tree for the Nix Expressions Language. NixEl is a Rust library that turns Nix code in

Kevin Amado 48 Sep 16, 2022
Obake is a procedural macro for declaring and maintaining versioned data-structures.

Obake is a procedural macro for declaring and maintaining versioned data-structures. The name 'obake' is taken from the Japanese 'お化け (おばけ)', a class of supernatural beings in Japanese folklore that shapeshift.

Nathan Corbyn 164 Sep 13, 2022
Fast, efficient, and robust memory reclamation for concurrent data structures

Seize Fast, efficient, and robust memory reclamation for concurrent data structures. Introduction Concurrent data structures are faced with the proble

Ibraheem Ahmed 228 Sep 21, 2022
Garbage Collector(Hyaline- Safe Memory Reclaimation) for lock free data structures

Hyaline-SMR This crate provides garbage collection using hyaline algorithm for building concurrent data structures. When a thread removes an object fr

Abishek 1 Oct 21, 2021
Library containing implementations of various sequential data-structures.

Library containing implementations of various sequential data-structures.

c1m50c 0 May 15, 2022
Untree converts tree diagrams produced by tree back into directory file structures.

Untree: Undoing tree for fun and profit Untree converts tree diagrams produced by tree back into directory file structures. Let's say you have the fol

Alecto Irene Perez 92 Jun 24, 2022