Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Which helper I can use to split this string?
Forum Updated to NodeBB v4.3 + New Features

Which helper I can use to split this string?

Scheduled Pinned Locked Moved Unsolved General and Desktop
10 Posts 3 Posters 911 Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    Mark81
    wrote on last edited by Mark81
    #1

    I'm facing a lot of trouble parsing a simple YAML string. Here an example:

    {CR: {cmd: fade, color: blue, panel: 0, value: 30, fout: 0.5, fint: 5}, OL: {cmd: text, value: Blu at 30% on all, color: white, time: 5, position: [540,100], size: 50}}
    

    My goal is to retrieve the two root objects:

    CR: {cmd: fade, color: blue, panel: 0, value: 30, fout: 0.5, fint: 5}
    OL: {cmd: text, value: Blu at 30% on all, color: white, time: 5, position: [540,100], size: 50}
    

    I'm using libYaml with the Qt wrapper. With this function I can retrieve the two root keys:

    bool SEMTools::decodeYaml(QString yaml)
    {
        try
        {
            YAML::Node root = YAML::Load(yaml.toStdString().c_str());
            YAML::Node::iterator i;
            for (i = root.begin(); i != root.end(); i++)
            {
                qDebug() << (*i).first.as<QString>();
            }
            return true;
        }
        catch (YAML::TypedBadConversion<QString> const &e)
        {
            qDebug() << e.what();
        }
    
        return false;
    }
    

    it outputs:

    CR
    OL
    

    But how to get the whole string?
    This:

    qDebug() << (*i).as<QString>();
    

    leads to:

    terminate called after throwing an instance of 'YAML::InvalidNode'
    what():  invalid node; this may result from using a map iterator as a sequence iterator, or vice-versa
    

    How to use this wrapper to get the strings above?
    Otherwise, how I can split the initial string into the two required? I'm not sure how to easily identify the comma that divides the two objects....

    JonBJ 1 Reply Last reply
    0
    • M Mark81

      I'm facing a lot of trouble parsing a simple YAML string. Here an example:

      {CR: {cmd: fade, color: blue, panel: 0, value: 30, fout: 0.5, fint: 5}, OL: {cmd: text, value: Blu at 30% on all, color: white, time: 5, position: [540,100], size: 50}}
      

      My goal is to retrieve the two root objects:

      CR: {cmd: fade, color: blue, panel: 0, value: 30, fout: 0.5, fint: 5}
      OL: {cmd: text, value: Blu at 30% on all, color: white, time: 5, position: [540,100], size: 50}
      

      I'm using libYaml with the Qt wrapper. With this function I can retrieve the two root keys:

      bool SEMTools::decodeYaml(QString yaml)
      {
          try
          {
              YAML::Node root = YAML::Load(yaml.toStdString().c_str());
              YAML::Node::iterator i;
              for (i = root.begin(); i != root.end(); i++)
              {
                  qDebug() << (*i).first.as<QString>();
              }
              return true;
          }
          catch (YAML::TypedBadConversion<QString> const &e)
          {
              qDebug() << e.what();
          }
      
          return false;
      }
      

      it outputs:

      CR
      OL
      

      But how to get the whole string?
      This:

      qDebug() << (*i).as<QString>();
      

      leads to:

      terminate called after throwing an instance of 'YAML::InvalidNode'
      what():  invalid node; this may result from using a map iterator as a sequence iterator, or vice-versa
      

      How to use this wrapper to get the strings above?
      Otherwise, how I can split the initial string into the two required? I'm not sure how to easily identify the comma that divides the two objects....

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #2

      @Mark81
      Funnily enough, although I have never used YAML, I was reading this week how it is a superset of JSON. I can relate to your string as though it were parseable as JSON. In that situation the values of your nodes are not strings or QStrings --- presumably hence your error message --- they are JSON/YAML objects. Look in your libYaml documentation for what type it uses for these "objects", and then look for a method on the object for serializing it as a string.

      Otherwise, how I can split the initial string into the two required? I'm not sure how to easily identify the comma that divides the two objects....

      As an answer to that question: QString::split("},") or QString::split(QRegularExpression("}\\s*,")), would be a one-line dirty solution. Would I recommend it? No, it's not at all robust, and will only work if the input looks just like you show. But if all you want to do is split that particular input, you can't be bothered to do it properly and want a solution in 10 seconds, there you are!

      M 1 Reply Last reply
      0
      • JonBJ JonB

        @Mark81
        Funnily enough, although I have never used YAML, I was reading this week how it is a superset of JSON. I can relate to your string as though it were parseable as JSON. In that situation the values of your nodes are not strings or QStrings --- presumably hence your error message --- they are JSON/YAML objects. Look in your libYaml documentation for what type it uses for these "objects", and then look for a method on the object for serializing it as a string.

        Otherwise, how I can split the initial string into the two required? I'm not sure how to easily identify the comma that divides the two objects....

        As an answer to that question: QString::split("},") or QString::split(QRegularExpression("}\\s*,")), would be a one-line dirty solution. Would I recommend it? No, it's not at all robust, and will only work if the input looks just like you show. But if all you want to do is split that particular input, you can't be bothered to do it properly and want a solution in 10 seconds, there you are!

        M Offline
        M Offline
        Mark81
        wrote on last edited by
        #3

        @JonB unfortunately these are only the (in)famous minimal and reproducible examples.... the real YAML objects (and then braces) can be nested. But at the end, I only need to retrieve each whole objects at root level.

        JonBJ 1 Reply Last reply
        0
        • M Mark81

          @JonB unfortunately these are only the (in)famous minimal and reproducible examples.... the real YAML objects (and then braces) can be nested. But at the end, I only need to retrieve each whole objects at root level.

          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by
          #4

          @Mark81
          Understood. Then don't use the "split", which was beyond hacky anyway.

          I am finding no formal documentation of libYaml, we need to see what is available in the API? From looking at https://github.com/yaml/libyaml/blob/master/examples/mapping.yaml, does YAML/that library refer to what I called "objects" in JSON as mappings in YAML?

          M 1 Reply Last reply
          0
          • JonBJ JonB

            @Mark81
            Understood. Then don't use the "split", which was beyond hacky anyway.

            I am finding no formal documentation of libYaml, we need to see what is available in the API? From looking at https://github.com/yaml/libyaml/blob/master/examples/mapping.yaml, does YAML/that library refer to what I called "objects" in JSON as mappings in YAML?

            M Offline
            M Offline
            Mark81
            wrote on last edited by
            #5

            @JonB as far as understand, that example just shows a simple YAML usage: mapping pairs of key-values.

            JonBJ 1 Reply Last reply
            0
            • M Mark81

              @JonB as far as understand, that example just shows a simple YAML usage: mapping pairs of key-values.

              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by
              #6

              @Mark81
              ...which is what your "objects" contain, hence I was suggesting these are called "mappings" in YAML/libYaml and so what you should be looking up.

              • I asked where you get the written documentation for libYaml (its API) from? Without that neither of us can know what code you need.

              • Why are you seeking the string-text of these (sub-)nodes? The libYaml parser is deserializing the string input. It will (almost certainly) not offer you access to the original, non-parsed text for each element. You will likely have to re-produce that from the parsed tree by serializing the individual nodes. And for all I know libYaml is a deserializer only and may not even offer that. Why can't you used the resulting parsed tree for the nodes instead of wanting to turn them back into text, which would be simpler?

              M 1 Reply Last reply
              0
              • JonBJ JonB

                @Mark81
                ...which is what your "objects" contain, hence I was suggesting these are called "mappings" in YAML/libYaml and so what you should be looking up.

                • I asked where you get the written documentation for libYaml (its API) from? Without that neither of us can know what code you need.

                • Why are you seeking the string-text of these (sub-)nodes? The libYaml parser is deserializing the string input. It will (almost certainly) not offer you access to the original, non-parsed text for each element. You will likely have to re-produce that from the parsed tree by serializing the individual nodes. And for all I know libYaml is a deserializer only and may not even offer that. Why can't you used the resulting parsed tree for the nodes instead of wanting to turn them back into text, which would be simpler?

                M Offline
                M Offline
                Mark81
                wrote on last edited by Mark81
                #7

                @JonB The only "docs" I can find is the one you've already pointed out: https://github.com/yaml/libyaml. I neither can find more... I agree it's hard without, but of course if it was well-documented I would not post here :-)

                I need the whole string for each root-object because I need to understand the type of content before deserializing them!
                I defined a lot of "objects", each one starting with a specific key:

                CR: {...}
                AB: {...}
                SY: {...}
                ST: {...}
                HJ: {...}
                

                They can be joined at root-level in one in-line YAML:

                {CR: {...}, AB: {...}, ST: {...}}
                

                Because they have different fields, for each one I wrote a deserializing function, example:

                bool DBCCromoUtils::decodeCromoFade(QString yaml, int *color, int *panel, int *val, qreal *fade_in, qreal *fade_out)
                {
                    QString command;
                
                    YAML::Node root = YAML::Load(yaml.toStdString().c_str());
                    YAML::Node node = root["CR"];
                    if (node.IsNull()) return false;
                
                    YAML::convert<QString>().decode(node["cmd"], command);
                    if (command != "fade") return false;
                
                    YAML::convert<int>().decode(node["color"], *color);
                    YAML::convert<int>().decode(node["panel"], *panel);
                    YAML::convert<int>().decode(node["value"], *val);
                    YAML::convert<qreal>().decode(node["fin"], *fade_in);
                    YAML::convert<qreal>().decode(node["fout"], *fade_out);
                    return true;
                }
                

                In order to work I need to pass to this function only the YAML portion that belong to this "object".

                JonBJ 1 Reply Last reply
                0
                • M Mark81

                  @JonB The only "docs" I can find is the one you've already pointed out: https://github.com/yaml/libyaml. I neither can find more... I agree it's hard without, but of course if it was well-documented I would not post here :-)

                  I need the whole string for each root-object because I need to understand the type of content before deserializing them!
                  I defined a lot of "objects", each one starting with a specific key:

                  CR: {...}
                  AB: {...}
                  SY: {...}
                  ST: {...}
                  HJ: {...}
                  

                  They can be joined at root-level in one in-line YAML:

                  {CR: {...}, AB: {...}, ST: {...}}
                  

                  Because they have different fields, for each one I wrote a deserializing function, example:

                  bool DBCCromoUtils::decodeCromoFade(QString yaml, int *color, int *panel, int *val, qreal *fade_in, qreal *fade_out)
                  {
                      QString command;
                  
                      YAML::Node root = YAML::Load(yaml.toStdString().c_str());
                      YAML::Node node = root["CR"];
                      if (node.IsNull()) return false;
                  
                      YAML::convert<QString>().decode(node["cmd"], command);
                      if (command != "fade") return false;
                  
                      YAML::convert<int>().decode(node["color"], *color);
                      YAML::convert<int>().decode(node["panel"], *panel);
                      YAML::convert<int>().decode(node["value"], *val);
                      YAML::convert<qreal>().decode(node["fin"], *fade_in);
                      YAML::convert<qreal>().decode(node["fout"], *fade_out);
                      return true;
                  }
                  

                  In order to work I need to pass to this function only the YAML portion that belong to this "object".

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by
                  #8

                  @Mark81 said in Which helper I can use to split this string?:

                  The only "docs" I can find is the one you've already pointed out: https://github.com/yaml/libyaml. I neither can find more...

                  Then I wish you all the best, because (politely) the only way to help you/solve your problem is to write the code and hack around with it to see what is going on and what the library offers, and you will have to do that. Or hope a libYaml expert pops by....

                  M 1 Reply Last reply
                  0
                  • JonBJ JonB

                    @Mark81 said in Which helper I can use to split this string?:

                    The only "docs" I can find is the one you've already pointed out: https://github.com/yaml/libyaml. I neither can find more...

                    Then I wish you all the best, because (politely) the only way to help you/solve your problem is to write the code and hack around with it to see what is going on and what the library offers, and you will have to do that. Or hope a libYaml expert pops by....

                    M Offline
                    M Offline
                    Mark81
                    wrote on last edited by
                    #9

                    @JonB understood. I thought it was a very easy task and I was blind to see the solution.

                    1 Reply Last reply
                    0
                    • SGaistS Offline
                      SGaistS Offline
                      SGaist
                      Lifetime Qt Champion
                      wrote on last edited by
                      #10

                      Hi,

                      Just in case, there's a Qt wrapper for libyaml that might be easier to use.

                      One thing that is not clear is why do you need the string representation to know how to deserialise the block ?

                      Usually, you structure should be well defined and thus you should either have the name of the mapping allowing to know what is inside it and thus use a dedicated function to extract the data you want or you should have a specific field in your structure that will again allow you to know to which function you want to send it for further processing.

                      Interested in AI ? www.idiap.ch
                      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved