# 187. Object Serialization with pickle and json

**1. Serialize and Deserialize with `pickle`**

```python
import pickle

data = {'name': 'Alice', 'age': 25, 'city': 'Wonderland'}
# Serialize
with open('data.pkl', 'wb') as f:
    pickle.dump(data, f)

# Deserialize
with open('data.pkl', 'rb') as f:
    loaded_data = pickle.load(f)

print(loaded_data)
```

***

**2. Serialize Multiple Objects with `pickle`**

```python
import pickle

data1 = [1, 2, 3]
data2 = {'a': 10, 'b': 20}

with open('multi_data.pkl', 'wb') as f:
    pickle.dump(data1, f)
    pickle.dump(data2, f)

with open('multi_data.pkl', 'rb') as f:
    loaded_data1 = pickle.load(f)
    loaded_data2 = pickle.load(f)

print(loaded_data1, loaded_data2)
```

***

**3. Serialize Custom Objects with `pickle`**

```python
import pickle

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __repr__(self):
        return f'Person(name={self.name}, age={self.age})'

p = Person('Bob', 30)

# Serialize
with open('person.pkl', 'wb') as f:
    pickle.dump(p, f)

# Deserialize
with open('person.pkl', 'rb') as f:
    loaded_person = pickle.load(f)

print(loaded_person)
```

***

**4. Serialize and Deserialize with `json`**

```python
import json

data = {'name': 'Alice', 'age': 25, 'city': 'Wonderland'}

# Serialize
with open('data.json', 'w') as f:
    json.dump(data, f)

# Deserialize
with open('data.json', 'r') as f:
    loaded_data = json.load(f)

print(loaded_data)
```

***

**5. Serialize Python Objects to JSON String**

```python
import json

data = {'name': 'Alice', 'hobbies': ['reading', 'traveling']}
json_string = json.dumps(data)

print(json_string)
loaded_data = json.loads(json_string)
print(loaded_data)
```

***

**6. Serialize Custom Objects with `json` Using `default` Argument**

```python
import json

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

def person_encoder(obj):
    if isinstance(obj, Person):
        return {'name': obj.name, 'age': obj.age}
    raise TypeError(f'Object of type {type(obj)} is not JSON serializable')

p = Person('Bob', 30)
json_data = json.dumps(p, default=person_encoder)
print(json_data)
```

***

**7. Deserialize Custom JSON with `object_hook`**

```python
import json

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

def person_decoder(d):
    if 'name' in d and 'age' in d:
        return Person(d['name'], d['age'])
    return d

json_data = '{"name": "Alice", "age": 25}'
person = json.loads(json_data, object_hook=person_decoder)

print(person.__dict__)
```

***

**8. Use `pickle` for Serializing Large Data**

```python
import pickle

large_data = [i ** 2 for i in range(10**6)]
with open('large_data.pkl', 'wb') as f:
    pickle.dump(large_data, f)

with open('large_data.pkl', 'rb') as f:
    loaded_large_data = pickle.load(f)

print(len(loaded_large_data))
```

***

**9. Handling Encoding and Decoding Issues in `json`**

```python
import json

data = {'name': 'Alice', 'age': 25, 'message': 'Hello, 世界!'}
json_data = json.dumps(data, ensure_ascii=False)
print(json_data)

loaded_data = json.loads(json_data)
print(loaded_data)
```

***

**10. Serialize and Deserialize Nested Data Structures**

```python
import json

nested_data = {
    'name': 'Alice',
    'details': {
        'age': 25,
        'hobbies': ['reading', 'cycling']
    }
}

# Serialize
with open('nested_data.json', 'w') as f:
    json.dump(nested_data, f, indent=4)

# Deserialize
with open('nested_data.json', 'r') as f:
    loaded_nested_data = json.load(f)

print(loaded_nested_data)
```

***
