My feature branch to issue #19129  (read_json and orient='table' With Numeric Column)
State: closed

- [x] closes #[19129 ](https://github.com/pandas-dev/pandas/issues/19129)
- [x] [Tests added and passed
- [x] All [code checks passed
- [ ] Added [type annotations](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#type-hints) to new arguments/methods/functions.
- [x] Added an entry in the latest `doc/source/whatsnew/vX.X.X.rst` file if fixing a bug or adding a new feature.

### New Behavior

The following code will now raise a `ValueError` with the message: 

#### Example:
```python
import pandas as pd

# Create DataFrame with numeric column names
df = pd.DataFrame([[1, 2, 3, 4]], columns=[5, 6, 7, 8])

# Attempt to serialize to JSON with 'table' orient
df.to_json('test.json', orient='table')


ValueError: Column names must be strings for JSON serialization with orient='table'.
```

Note : This is my first attempt at contributions. So, I would like to point out that there might be flaws and would appreciate any feedback.

Labels:
name: IO JSON
description: read_json, to_json, json_normalize
name: Stale

Comments:
changed the approach slightly from checking only for numeric column names.
The implementation now checks and raises the ValueError if any non string column name is used.
The issue here I don't think is as finely scoped as the comments would suggest. AFAIU there is nothing specific to the table format that takes a stance on whether numeric values can be the keys of an object. However, the base JSON specification requires that object keys are strings:

https://www.json.org/json-en.html

There is a balance that needs to be struck here between being pedantic and pragmatic; do none of the other formats serialize object keys as strings?
Hi @WillAyd,

I iterated over the other orient values to check the behaviour. It is as you have mentioned, the other formats do serialize the keys as string when saved as a json file.

```python

for orient in orients:
    try:
        # Save JSON
        df.to_json('test.json', orient=orient)
        
        # Read JSON
        read_df = pd.read_json('test.json', orient=orient)
        
        # Check column types after reading
        col_types = [type(col) for col in read_df.columns]
        
        results[orient] = {
            "Success": True,
            "Column Types": col_types,
            "DataFrame": read_df
        }
    except Exception as e:
        results[orient] = {
            "Success": False,
            "Error": str(e)
        }

```

And I can see that this is handled for other orients when the saved json is read back while preserving the int column types.


```python
{'records': {'Success': True,
  'Column Types': [int, int, int, int],
  'DataFrame':    5  6  7  8
  0  1  2  3  4},
 'index': {'Success': True,
  'Column Types': [int, int, int, int],
  'DataFrame':    5  6  7  8
  0  1  2  3  4},
 'columns': {'Success': True,
  'Column Types': [int, int, int, int],
  'DataFrame':    5  6  7  8
  0  1  2  3  4},
 'split': {'Success': True,
  'Column Types': [int, int, int, int],
  'DataFrame':    5  6  7  8
  0  1  2  3  4},
 'values': {'Success': True,
  'Column Types': [int, int, int, int],
  'DataFrame':    0  1  2  3
  0  1  2  3  4},
 'table': {'Success': False,
  'Error': "Cannot convert non-finite values (NA or inf) to integer: Error while type casting for column '5'"}}
       
 

Cool thanks. So if we do anything here I think it makes the most sense to serialize as strings but keep the dtype in the metadata of the table format as integral. 
I have tried a new approach by working on the parse_table_schema function to handle the numeric columns by initially converting them to string and then restoring their original types after the dataframe is formed.

I am now able to reproduce the same behaviour for orient='table'

```python
{'records': {'Success': True,
  'Column Types': [int, int, int, int],
  'DataFrame':    5  6  7  8
  0  1  2  3  4},
 'index': {'Success': True,
  'Column Types': [int, int, int, int],
  'DataFrame':    5  6  7  8
  0  1  2  3  4},
 'columns': {'Success': True,
  'Column Types': [int, int, int, int],
  'DataFrame':    5  6  7  8
  0  1  2  3  4},
 'split': {'Success': True,
  'Column Types': [int, int, int, int],
  'DataFrame':    5  6  7  8
  0  1  2  3  4},
 'values': {'Success': True,
  'Column Types': [int, int, int, int],
  'DataFrame':    0  1  2  3
  0  1  2  3  4},
 'table': {'Success': True,
  'Column Types': [int, int, int, int],
  'DataFrame':    5  6  7  8
  0  1  2  3  4}}
```
This pull request is stale because it has been open for thirty days with no activity. Please [update](https://pandas.pydata.org/pandas-docs/stable/development/contributing.html#updating-your-pull-request) and respond to this comment if you're still interested in working on this.
Hi @WillAyd 
Is this still up for consideration?
Can you add tests for the behavior you  are trying to achieve?
Hi @WillAyd ,
Sorry for the delay, I have added the test to check if to_json method retains the int column types when read back
Thanks for the pull request, but it appears to have gone stale. If interested in continuing, please merge in the main branch, address any review comments and/or failing tests, and we can reopen.