The base object wouldn't need to know anything about what the various values are used for- it would just need to know that a specific object has a given list of key/type/value information.
Exactly. Separation of serialization and logic.
Some more thoughts:
If you are using C++, and insist on using real C++ class members for all properties, and don't overlap editor and game objects, you can add "annotations" to class members for de/serialization, using some template magic.
E.g.
class A
{
int b;
float c;
}
class_<A> A_("A");
property(A_,"b", &B::b);
property(A_,"c", &B::c);
See Boost::Python for how succinct this can get. Because you don't need repeat type annotations, it's more convenient than a special file, or method.
Having made game objects, and made their contents available for introspection, you do not need to any further work for editor objects. Except for where the properties also affect the editor, you DO NOT need to duplicate the functionality of game objects. You just need a single editor object that which can read and write based on that property information.
The aim of the game is to avoid repeating yourself at all. Unfortunately, you must list still everything twice (once in the class definition, and once to declare it as a property) in C++, but that still sounds better than the 5 copies you appear to be doing (LevelReader, EditorObject::Write, GameObject::Write, GameObject class defintion, EditorObject class definition).
It's just a thought, though, I certainly haven't tried it.
Edit: There's a few C++ serialization solutions out there. Unless you are doing something special, it sounds like it's best to let someone else do the hard work for you.