...and what if the name contains two words with a blank in between??
Why do you need to invent your own format for serialization and de-serialization? why not use an industry standard like json, where you can utilize any of many libraries that can do the serialization and de-serialization.  Do you need me to show you how?
EDIT:
OK, it turned out that using json is not as straightforward as I initially thought. Don't get me wrong, it is still better than custom format in the sense that it is bug-proof and supports edge cases like the one I described above.
The obstacle with json is that the key to every object and property has to be a String. So when the key is a user defined type (like Person in your case) it didn’t get serialized properly - there is a need for a transitional data structure before the serialization to json can be performed.
So this is what I did: for each entry in your dictionary, I create a map that holds two entries: a "person" entry with the json String representation of the Person object, and a "pets" entry with the json String representation of the list of pets. So the final String to be serialized is actually a List of Maps.
To give you an idea: every map entry looks like this as json:
{
    "person":{"name":"AISEC","age":12,"sex":"MALE"},
    "pets":[
        {"name":"Loo","age":12,"type":"Cat"},
        {"name":"Kitty","age":4,"type":"Cat"}
    ]
}
The deserialization is simply the reverse operation.
I am using Jackson library as json parser and writer
This is the serialization method. it returns a String that can be written to a file:
public String dictToJson(Map<Person, List<Pet>> map) throws IOException
{
    ObjectMapper mapper = new ObjectMapper();
    // serialized dictionary is list of maps
    List<Map<String, String>> jsonDictionary = new ArrayList<>();
    for (Map.Entry<Person, List<Pet>> mapEntry : map.entrySet()) {
        // each map entry becomes its own map instance with two entries   
        Map<String, String> jsonEntry = new HashMap<>();
        // write person key as "person" with json string represetation of person object
        jsonEntry.put("person", mapper.writeValueAsString(mapEntry.getKey()));
        // write pets value as "pets" key with json string represetation of pets list
        jsonEntry.put("pets", mapper.writeValueAsString(mapEntry.getValue()));
        jsonDictionary.add(jsonEntry);
    }
    return mapper.writeValueAsString(jsonDictionary);
}
The de-serialization method accpets String (whole content of file):
public Map<Person, List<Pet>> jsonToDict(String json) throws IOException
{
    Map<Person, List<Pet>> map = new HashMap<>();
    ObjectMapper mapper = new ObjectMapper();
    // read json String into list of maps
    List<Map<String, String>> jsonDictionary = 
            mapper.readValue(json, new TypeReference<List<Map<String, Object>>>(){});
    // each list item is a map with two entries 
    for (Map<String, String> jsonEntry : jsonDictionary) {
        map.put(
                mapper.readValue(jsonEntry.get("person"), Person.class), 
                mapper.readValue(jsonEntry.get("pets"), new TypeReference<List<Pet>>(){}));
    }
    return map;
}
usage and test method:
public static void main(String[] args)
{
    Map<Person, List<Pet>> map ; {
        map = new HashMap<>();
        map.put(new Person("JOHN", 10, "MALE"), 
                Arrays.asList(new Pet[]{new Pet("Spot", 3, "Dog")}));
        map.put(new Person("AISEC", 12, "MALE"), 
                Arrays.asList(new Pet[]{new Pet("Loo", 12, "Cat"), new Pet("Kitty", 4, "Cat")}));
    }
    try {
        // serialize map into String
        String serializedDict = dictToJson(map);
        // write to file ...
        System.out.println(serializedDict);
        map.clear();
        // de-serialize from String to map 
        map = jsonToDict(serializedDict);
        // check if map was built ok 
        System.out.println(dictToJson(map));
    } catch (Exception e) {
        e.printStackTrace();
    }
}