I'm creating a MUD and am running into some design issues regarding Items.

Items are stored in an ItemDatabase after being read from a JSON file. 

    template <typename ItemType>
	static void load(std::string const& filename)
	{
		PropertyTree propertyTree;
		boost::property_tree::read_json(filename, propertyTree);
		
		for (auto& jsonItem : propertyTree)
		{
			Item *item = new ItemType();
			item->fromJson(jsonItem);

			database_[item->id()] = item;
		}
	}

At first, every Database::find() returned a shallow copy of the item, however, this quickly becomes dangerous and erroneous when items have a finite usage, e.g. a life potion that is consumed after one charge.

Therefore, I want to start returning deep copies as std::unique_ptrs because each Item is unique and is possessed by only one entity. This avoids dangerous dangling pointers, if the Item is not maintained or destroyed by the caller:

    template <typename DataType>
    std::unique_ptr<DataType> EntityDatabase<DataType>::find(EntityId const& entityId)
    {
	    auto found = std::find_if(std::begin(database_), std::end(database_), 
							      [&entityId](Container::value_type const& candidate)
							      {
								      return (candidate.second->id() == entityId);
							      });

	    if (found != std::end(database_))
		    return std::unique_ptr<DataType>(new DataType(*found->second));
	    else
		    return nullptr;
    }

However, the resulting code is worse than hideous. Consider turning an `Item` into a `Weapon`:

	void Inventory::fromJson(PropertyTree::value_type const& properties)
	{
		auto jsonInventory = *properties.second.find("Inventory");

		auto weaponId = getValue<EntityId>(jsonInventory, "Weapon");
		weapon_.reset(static_cast<Weapon*>(ItemDatabase::find(weaponId).release()));

		auto armorId  = getValue<EntityId>(jsonInventory, "Armor");
		armor_.reset(static_cast<Armor*>(ItemDatabase::find(armorId).release()));

		money_ = getValue<Money>(jsonInventory, "Money");

		for (auto& item : jsonInventory.second.get_child("Items"))
		{
			auto itemId = boost::lexical_cast<EntityId, std::string>(item.second.data());
			inventory_.push_back(std::move(ItemDatabase::find(itemId)));
		}
	}

How can I improve the code or the design?