C# - 从Google Place Api中提取营业时间

时间:2016-12-04 13:58:31

标签: c# json asp.net-mvc-4 json.net

我正在使用Google Place Api Json:

{
    "html_attributions": ["Listings by \u003ca href=\"http://www.openrice.com/\"\u003eOpenRice\u003c/a\u003e"],
    "result": {
        "address_components": [{
            "long_name": "Bayfield Building",
            "short_name": "Bayfield Building",
            "types": ["premise"]
        }, {
            "long_name": "99",
            "short_name": "99",
            "types": ["street_number"]
        }, {
            "long_name": "Hennessy Road",
            "short_name": "Hennessy Rd",
            "types": ["route"]
        }, {
            "long_name": "Wan Chai",
            "short_name": "Wan Chai",
            "types": ["neighborhood", "political"]
        }, {
            "long_name": "Hong Kong Island",
            "short_name": "Hong Kong Island",
            "types": ["administrative_area_level_1", "political"]
        }, {
            "long_name": "Hong Kong",
            "short_name": "HK",
            "types": ["country", "political"]
        }],
        "adr_address": "Bayfield Building, \u003cspan class=\"street-address\"\u003e99 Hennessy Rd\u003c/span\u003e, \u003cspan class=\"locality\"\u003eWan Chai\u003c/span\u003e, \u003cspan class=\"country-name\"\u003eHong Kong\u003c/span\u003e",
        "formatted_address": "Bayfield Building, 99 Hennessy Rd, Wan Chai, Hong Kong",
        "formatted_phone_number": "2529 3338",
        "geometry": {
            "location": {
                "lat": 22.2775876,
                "lng": 114.1719815
            }
        },
        "icon": "https://maps.gstatic.com/mapfiles/place_api/icons/restaurant-71.png",
        "id": "b787af8ba2c2037cb18f4c9ccfa6686c58637981",
        "international_phone_number": "+852 2529 3338",
        "name": "Happy Veggies",
        "opening_hours": {
            "open_now": false,
            "periods": [{
                "close": {
                    "day": 0,
                    "time": "2300"
                },
                "open": {
                    "day": 0,
                    "time": "1030"
                }
            }, {
                "close": {
                    "day": 1,
                    "time": "1430"
                },
                "open": {
                    "day": 1,
                    "time": "1130"
                }
            }, {
                "close": {
                    "day": 1,
                    "time": "2200"
                },
                "open": {
                    "day": 1,
                    "time": "1800"
                }
            }, {
                "close": {
                    "day": 2,
                    "time": "1430"
                },
                "open": {
                    "day": 2,
                    "time": "1130"
                }
            }, {
                "close": {
                    "day": 2,
                    "time": "2200"
                },
                "open": {
                    "day": 2,
                    "time": "1800"
                }
            }, {
                "close": {
                    "day": 3,
                    "time": "1430"
                },
                "open": {
                    "day": 3,
                    "time": "1130"
                }
            }, {
                "close": {
                    "day": 3,
                    "time": "2200"
                },
                "open": {
                    "day": 3,
                    "time": "1800"
                }
            }, {
                "close": {
                    "day": 5,
                    "time": "1430"
                },
                "open": {
                    "day": 5,
                    "time": "1130"
                }
            }, {
                "close": {
                    "day": 5,
                    "time": "2200"
                },
                "open": {
                    "day": 5,
                    "time": "1800"
                }
            }, {
                "close": {
                    "day": 6,
                    "time": "1430"
                },
                "open": {
                    "day": 6,
                    "time": "1130"
                }
            }, {
                "close": {
                    "day": 6,
                    "time": "2200"
                },
                "open": {
                    "day": 6,
                    "time": "1800"
                }
            }],
            "weekday_text": ["Monday: 11:30 AM – 2:30 PM, 6:00 – 10:00 PM", "Tuesday: 11:30 AM – 2:30 PM, 6:00 – 10:00 PM", "Wednesday: 11:30 AM – 2:30 PM, 6:00 – 10:00 PM", "Thursday: Closed", "Friday: 11:30 AM – 2:30 PM, 6:00 – 10:00 PM", "Saturday: 11:30 AM – 2:30 PM, 6:00 – 10:00 PM", "Sunday: 11:30 AM – 2:30 PM"]
        },
        "photos": [{
            "height": 1373,
            "html_attributions": ["\u003ca href=\"https://maps.google.com/maps/contrib/109496796118538295490/photos\"\u003eHappy Veggies\u003c/a\u003e"],
            "photo_reference": "CoQBcwAAAEQZPA8WYu4ICwr--n4gCE7uyinkzAdRguvnTLHJD2xiqgUbmzkiMjP_MyzKt4Vdtb46wrLIC33LmvZqKB9avWMEjeSioVgAFPapKOlzpZKfEKEeapW5dQw7_Tx3f5QHrmN2VGQx3DCVS7BKi-wxfJNzbHwpHHIlHHUUlR_XOqDwEhDjmrQwOmJG1fndPu9BKsJ4GhT2PlTXf6cbqF8gUPDm8SMAnXw3WQ",
            "width": 1373
        }, {
            "height": 1536,
            "html_attributions": ["\u003ca href=\"https://maps.google.com/maps/contrib/109496796118538295490/photos\"\u003eHappy Veggies\u003c/a\u003e"],
            "photo_reference": "CoQBcwAAAMJJ7kMtGwTU9s0ovCjH6jT3BbPTrL88hXGWSeKSKH4VdBcWV3NBqw3OekIy1UGyeGzYxbxbgTVyr8ICxyT2uK0R8fTyFqd_EyJPGzlLa8pU3l3uX3eJRD24nUscVGukojyo02u_R0r56bHBTxbcm5pjtHQPdY0fhlZ1-e8v9MoYEhCOHRNLFUGv5WYYfJnn-_d1GhR7OhmJsrYolDf4VBl-EuktkM-5Dw",
            "width": 2048
        }, {
            "height": 497,
            "html_attributions": ["\u003ca href=\"https://maps.google.com/maps/contrib/109496796118538295490/photos\"\u003eHappy Veggies\u003c/a\u003e"],
            "photo_reference": "CoQBcwAAAA0pkWFzMfsRY-MJEzoXkdj4IN5fPEg1eeQz6kjH2rVHN2yJc7VeO7_sG718W-WMAwTHZYhs_fNA8yB5NxemJxsgDsgcOEYhZ-wUxFhgI6Hoo0fisOIhF5q84YhV5SukNbX8mHJvYSLzphEt_gT41HZlnAMOsLe1eWEdSL2S8n1REhChG5m3Q8EBDNwrSWYPmZe4GhTV0wssb2CdwQPiaWVNdE9XJMEonQ",
            "width": 471
        }, {
            "height": 426,
            "html_attributions": ["\u003ca href=\"https://maps.google.com/maps/contrib/109496796118538295490/photos\"\u003eHappy Veggies\u003c/a\u003e"],
            "photo_reference": "CoQBcwAAAALlkDVQcNsLN7im-tGd0U7TDchQkcsfn_0M1bHNs2yYozzsnhlzdUPiKRjZFgP_KnYG81w4suNMmee1GFNXtnXNmv1wybFuQ8-xOHd_sGpDDl5zNlKXOH9AcnXzQdsNmMFycxHYdK6rYhO4kOo7YLtt6lF7WgtDgmlBYqUE-yoXEhD-W8FUa2t3jwCeXpPRv_dEGhQ0gVhjmGyq87QIGk_Bowrgmv7nEA",
            "width": 640
        }, {
            "height": 1536,
            "html_attributions": ["\u003ca href=\"https://maps.google.com/maps/contrib/109496796118538295490/photos\"\u003eHappy Veggies\u003c/a\u003e"],
            "photo_reference": "CoQBcwAAACEn-ildhEyOgoPbwQGMFPkbFebvqhlahs0BOtZJ9tCw0tIJJ4adZZqyjupnXzNdPr19pLS56KroZdZ1ZNCMaJTypmI5lBH5Z2lfXrHjbVHsFe-s_gPar4A39O-9YPaQZv8CqYFx-i1x4YDz8UP-CQP1ftFmGtxk7751yeK6vUcgEhDt1WS1dybROHbC-Gs2PmLBGhQ-0lnbTr_PAMviMNyPbCxrIZmL2A",
            "width": 2048
        }, {
            "height": 2048,
            "html_attributions": ["\u003ca href=\"https://maps.google.com/maps/contrib/109496796118538295490/photos\"\u003eHappy Veggies\u003c/a\u003e"],
            "photo_reference": "CoQBcwAAAEzl1eyD61BiO4HsQx7A5jpO9i67UrIfXzfoGEueaDrJj0FgOZVgXNpYsN9nNVVF6zasWLe8aSbxgeuGlGTdsk6U6pS1zcNkxU1iqWCCQcxcCGLvYO_C2GR3qoDn-UODSam0r86U6aSdueqzy8kGahLCN2zcK8ctwpl0w1b7EZg3EhC28QM7UPm1VTsWOyYFpngbGhREwyF8qyITAlgwN-SG83V-lK2Tcg",
            "width": 1536
        }, {
            "height": 617,
            "html_attributions": ["\u003ca href=\"https://maps.google.com/maps/contrib/109496796118538295490/photos\"\u003eHappy Veggies\u003c/a\u003e"],
            "photo_reference": "CoQBcwAAADWrOhfim4ZmsbNrq2Hh816DEuVuO6IVNizs5tGL9B9F9S2_nK73Wf06MAlLP1TJoAmXtxhgtSKOz9cb4BBmt8pvn7panyVON4WbdI3WPwkMrIBwAs7EH-YT4UR3iAXZAHKi8i6EOlsAqYE9vaZRBDuN-z1gdr2N1DF8docak42YEhAzby18TkQgTCcGFNxsh53bGhThKRyxqQsOCEE6dRvmcLPxaARfug",
            "width": 823
        }, {
            "height": 656,
            "html_attributions": ["\u003ca href=\"https://maps.google.com/maps/contrib/109496796118538295490/photos\"\u003eHappy Veggies\u003c/a\u003e"],
            "photo_reference": "CoQBcwAAAPigk5WL5k_ygcIcbOmLj2RdvhoUnNVvtxw4IibLoOcm4iPUNVvWHs6Tisk9DCat2isgu4tb9WClk2y9N7-TLhlYPZc3hNtQode7bLMVA38_xJjDP4N9lOF5SJOmdqV2GQJubAydGt2ilHttRfRF3CJC7mg78flSSBbz2qAX6mBgEhCxUYB4wcO7cpUTUFdqFEVmGhRQHHccNROeTdlqlfRZ7c0_KJjduQ",
            "width": 873
        }, {
            "height": 612,
            "html_attributions": ["\u003ca href=\"https://maps.google.com/maps/contrib/109496796118538295490/photos\"\u003eHappy Veggies\u003c/a\u003e"],
            "photo_reference": "CoQBcwAAAIysZFfMl2raeOg7mfjM6JUYSolIXV_eHz3_bgF7TEjowLiewiX5wOuQ1sEjpQ0awnie7j3dLuD83xfeWkWjbWkH2S8n7FAIp50kTX8qHt7CPNalngIIC7L897TG0-R-r038G19lon3WTpax3Jnbnl5KZR0DwO-kwW91KDiZ4evWEhDH8uY-V5s7GQ7eC6ItEX84GhQsPl_-wgk4gH4-oXCY_HXS__2iTA",
            "width": 816
        }, {
            "height": 578,
            "html_attributions": ["\u003ca href=\"https://maps.google.com/maps/contrib/109496796118538295490/photos\"\u003eHappy Veggies\u003c/a\u003e"],
            "photo_reference": "CoQBcwAAAB956t7YS0IV9YDIdetEEoyqXwMjTLJyx1nRZnC-VMrBrkwh_K-LopmYCcL3QsOFEPHUm6VM4IxduGDNGxglkwJN_ITfI8RbZkTWzRJOTtKM6IMfa1BZYTBDu4GKOcYEYsWMapIhyRow8VzqBXnBy7KoFCoH9et-QS0cglZbsK2sEhAtZKNN1uMe2m2IqrV8fDKnGhQ1xxTzthWr219DDWNjzMdVPUMPiw",
            "width": 582
        }],
        "place_id": "ChIJn3Z-9FwABDQR8viBEIexpBk",
        "rating": 4.1,
        "reference": "CmRgAAAA0ByNliXqngNLcbGvQbQavXzFsoC4NJC_XTX1Zw4qJEifEKKA-ENokJXEsDurXhV_ab_oVWh6HKXYlE4bxdY70rDtyKRLQiE7cCNrAAYGzfMOgiJhafpgHKbdMJsBfEOuEhCu_B6ns2zKF11vkCs2qjo0GhRVNylMETQsQ8RRQoWwjRhW_R23Sg",
        "reviews": [{
            "aspects": [{
                "rating": 3,
                "type": "overall"
            }],
            "author_name": "Boris Zlatopolsky",
            "author_url": "https://plus.google.com/102033276533166804255",
            "language": "en",
            "profile_photo_url": "//lh6.googleusercontent.com/-cwVCIDebmuU/AAAAAAAAAAI/AAAAAAAA9Us/ZgWUAaRInrk/photo.jpg",
            "rating": 5,
            "text": "Thank you for putting up with another menu pointing foreigner. Well cooked vegetarian food. Was filled with locals which is always a good sign. Free WiFi ",
            "time": 1463145260
        }, {
            "aspects": [{
                "rating": 3,
                "type": "overall"
            }],
            "author_name": "Mark Chase",
            "author_url": "https://plus.google.com/107281325021421310105",
            "language": "en",
            "profile_photo_url": "//lh4.googleusercontent.com/--ECOxP2sh8U/AAAAAAAAAAI/AAAAAAAAAyI/WehjRN4DcgQ/photo.jpg",
            "rating": 5,
            "text": "Delicious healthy vegan food.  While the menu is in Chinese there are pictures of six items.  Pick any three and mark your items on an order slip.  The items come with a bowl of rice and tea and costs about $45 Hong Kong Dollars.  Desert and soy drinks cost extra.  It's on the 2nd floor (1st in local tradition), so use the elevator to get there. \n",
            "time": 1447665684
        }, {
            "aspects": [{
                "rating": 2,
                "type": "overall"
            }],
            "author_name": "Shih Rachel",
            "author_url": "https://plus.google.com/114669614384635257051",
            "language": "en",
            "rating": 4,
            "text": "Veggie can be nice too! ",
            "time": 1462295974
        }, {
            "aspects": [{
                "rating": 0,
                "type": "overall"
            }],
            "author_name": "Lawrenzo Lee",
            "author_url": "https://plus.google.com/113370010886257427075",
            "language": "en",
            "profile_photo_url": "//lh3.googleusercontent.com/-Vf5cBKiyFS8/AAAAAAAAAAI/AAAAAAAAui0/bKuRPNk-KIs/photo.jpg",
            "rating": 2,
            "text": "Saw this place on tv introduced as a place to give people who are deaf or hard of hearing a place to work. Thought it was well meaning and interesting so decided to have a visit. \n\nArrived I think around 11:30am. Walked in and was greeted by no one. The place was pretty much empty except for one table (more people came in later closer to lunch). Didn't quite know how this place operates and no one there to show us, so we picked a table ourself and sat down, waited, but no one came over to give us a menu or anything. \n\nWent over to the cashier and asked. Gave us a sheet where we can tick what we would like to order. The lunch menu you get to pick 3 dishes out of 6 and you get with it a bowl of soup and unlimited refill of rice (the rice is not the plain white ones but with added healthy red grains). This costs $42 per person, and each person MUST order one! I think it must be because they have free rice refills. At the time I wasn't feeling that well so I didn't wan't to eat but was forced (well could have walked out but we came all the from NT to try this place) to buy a lunch set each. I couldn't eat mine and my friend wasn't able to eat 2 sets so it was all wasted. Why do they have to have this rule? \n\nI wasn't able to eat much so the food review is from the friend I went with. The food was bland, a bit like hospital food, so guess that makes it healthy. The ingredients were not good quality, One of the dish was green cabbage but there was yellowing and \"stringy\" in the mouth. \n\nFor a place that promotes healthy eating, it does not show in the quality of their ingredients. And for a place that tries to help the handicapped in society, it's good someone is doing that but they also need to provide the training for the staff to work in this place. Even the manager there, who was not deaf, will do good with a bit of training as we had to walk up to him to ask for everything. \n\nGood intentions, but very disappointed by everything else!",
            "time": 1348137307
        }, {
            "aspects": [{
                "rating": 2,
                "type": "overall"
            }],
            "author_name": "Boris Thoenissen",
            "author_url": "https://plus.google.com/108970509270187901466",
            "language": "en",
            "profile_photo_url": "//lh3.googleusercontent.com/-7DrNKzLlJmI/AAAAAAAAAAI/AAAAAAAAG-A/5PZAQ_R48IE/photo.jpg",
            "rating": 4,
            "text": "Nice place to escape crowed HK",
            "time": 1408779193
        }],
        "scope": "GOOGLE",
        "types": ["restaurant", "food", "point_of_interest", "establishment"],
        "url": "https://maps.google.com/?cid=1847796940784400626",
        "utc_offset": 480,
        "vicinity": "Bayfield Building, 99 Hennessy Road",
        "website": "http://happyveggies99.blogspot.hk/"
    },
    "status": "OK"
}

我使用以下Model来反序列化Json文件:

public class GooglePlaceApiLocation
{
    public double lat { get; set; }
    public double lng { get; set; }
}

public class GooglePlaceApiNortheast
{
    public double lat { get; set; }
    public double lng { get; set; }
}

public class GooglePlaceApiSouthwest
{
    public double lat { get; set; }
    public double lng { get; set; }
}

public class GooglePlaceApiViewport
{
    public GooglePlaceApiNortheast northeast { get; set; }
    public GooglePlaceApiSouthwest southwest { get; set; }
}

public class GooglePlaceApiGeometry
{
    public GooglePlaceApiLocation location { get; set; }
    public GooglePlaceApiViewport viewport { get; set; }
}

public class GooglePlaceApiOpeningHours
{
    public bool open_now { get; set; }
    public List<GooglePlaceApiPeriod> periods { get; set; }
    public List<string> weekday_text { get; set; }
}
public class GooglePlaceApiPeriod
{
    public GooglePlaceApiOpenClose close { get; set; }
    public GooglePlaceApiOpenClose open { get; set; }
}
public class GooglePlaceApiOpenClose
{
    public int day { get; set; }
    public string time { get; set; }
}
public class GooglePlaceApiPhoto
{
    public int height { get; set; }
    public List<string> html_attributions { get; set; }
    public string photo_reference { get; set; }
    public int width { get; set; }
}

public class GooglePlaceApiResult
{
    public GooglePlaceApiGeometry geometry { get; set; }
    public string icon { get; set; }
    public string id { get; set; }
    public string name { get; set; }
    public string place_id { get; set; }
    public string reference { get; set; }
    public string scope { get; set; }
    public List<string> types { get; set; }
    public string vicinity { get; set; }
    public GooglePlaceApiOpeningHours opening_hours { get; set; }
    //public List<Photo> photos { get; set; }
    public double? rating { get; set; }
}

public class GooglePlaceApi
{
    public List<object> html_attributions { get; set; }
    public string next_page_token { get; set; }
    public GooglePlaceApiResult result { get; set; }
    public string status { get; set; }
}

我想提取opening_hours以使用以下模型构建新的List<OpenCloseDaysModel>

public class OpenCloseDaysModel
{
    public int day { get; set; }
    public List<OpenCloseResultModel> range { get; set; }
    public bool is_open { get; set; }
}
public class OpenCloseResultModel
{
    public string start { get; set; }
    public string end { get; set; }
}

我尝试使用以下功能:

    public async static Task<string> FormatOpenCloseFromGoogle(GooglePlaceApiOpeningHours GooglePlaceApiOpeningHours)
    {

        string Output = null;
        int CurrentDay = 0;
        string start = null;
        string end = null;

        OpenCloseDaysModel OpenCloseDaysModel = new OpenCloseDaysModel();
        List<OpenCloseDaysModel> OpenCloseDaysList = new List<OpenCloseDaysModel>();

        List<OpenCloseResultModel> OpenCloseResultModel = new List<OpenCloseResultModel>();

        //HttpContext.Current.Response.Write("<hr />" + JsonConvert.SerializeObject(GooglePlaceApiOpeningHours, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }) + "</ hr>");

        if (GooglePlaceApiOpeningHours != null)
        {
            foreach (var item in GooglePlaceApiOpeningHours?.periods)
            {
                TimeSpan tsstart;
                TimeSpan tsend;

                if (!TimeSpan.TryParse(item.open?.time?.Substring(0, 2) + ":" + item.open?.time?.Substring(2, 2), CultureInfo.InvariantCulture, out tsstart))
                {
                    return null;
                }
                else
                {
                    start = tsstart.ToString(@"hh\:mm");
                }
                if (!TimeSpan.TryParse(item.close?.time?.Substring(0, 2) + ":" + item.close?.time?.Substring(2, 2), CultureInfo.InvariantCulture, out tsend))
                {
                    return null;
                }
                else
                {
                    end = tsend.ToString(@"hh\:mm");
                }

                OpenCloseDaysModel.day = CurrentDay;

                if (item.open.day != CurrentDay)
                {
                    OpenCloseDaysModel.range = OpenCloseResultModel;
                    OpenCloseDaysList.Add(OpenCloseDaysModel);
                    OpenCloseDaysModel = new OpenCloseDaysModel();
                    OpenCloseResultModel = new List<OpenCloseResultModel>();
                    OpenCloseResultModel.Add(new OpenCloseResultModel { start = start, end = end });
                }
                else
                {
                    OpenCloseResultModel.Add(new OpenCloseResultModel { start = start, end = end });
                }
                CurrentDay = item.open.day;
            }

            OpenCloseDaysModel.day = CurrentDay;
            OpenCloseResultModel.Add(new OpenCloseResultModel { start = start, end = end });
            OpenCloseDaysModel.range = OpenCloseResultModel;
            OpenCloseDaysList.Add(OpenCloseDaysModel);

            List<OpenCloseDaysModel> OrderdOpenCloseDaysList = new List<OpenCloseDaysModel>();
            for (int i = 1; i < 7; i++)
            {
                var DayQuery = OpenCloseDaysList.OrderByDescending(o => o.day).Where(o => o.day == i).FirstOrDefault();
                if (DayQuery != null)
                {
                    OrderdOpenCloseDaysList.Add(new OpenCloseDaysModel { day = i, range = DayQuery.range, is_open = true });
                }
                else
                {
                    OrderdOpenCloseDaysList.Add(new OpenCloseDaysModel { day = i, range = null, is_open = false });
                }
            }
            //for sunday
            var DayQuerySunday = OpenCloseDaysList.Where(o => o.day == 0).FirstOrDefault();
            if (DayQuerySunday != null)
            {
                OrderdOpenCloseDaysList.Add(new OpenCloseDaysModel { day = 0, range = DayQuerySunday.range, is_open = true });
            }
            else
            {
                OrderdOpenCloseDaysList.Add(new OpenCloseDaysModel { day = 0, range = null, is_open = false });
            }
            Output = JsonConvert.SerializeObject(OrderdOpenCloseDaysList, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
        }


        return Output;
    }

但它返回了一些错误的价值...... 有没有更简单的方法来构建我的模型:OpenCloseDaysModel

1 个答案:

答案 0 :(得分:1)

我会使用LINQ方法在模型之间进行转换,然后填写缺失的日期,按日排序结果,最后序列化。也许是这样的:

def summarizeData(filename):
    #open the file and read the contents 
    with open(filename, 'r') as f:  
        data = f.read().splitlines()

    return data

使用您的示例数据,这会得到以下结果(为了便于阅读,我在此处添加了格式,但根据您的原始代码,上述输出未格式化):

public static string FormatOpenCloseFromGoogle(GooglePlaceApiOpeningHours openingHoursModel)
{
    if (openingHoursModel == null || openingHoursModel.periods == null) return null;

    // build a list of open days from Google data
    var list = openingHoursModel.periods
        .GroupBy(p => p.open.day)
        .Select(g => new OpenCloseDaysModel
        {
            day = g.Key,
            is_open = true,
            range = g.Select(p => new OpenCloseResultModel
                    {
                        start = p.open.time.Substring(0, 2) + ":" + p.open.time.Substring(2, 2),
                        end = p.close != null ? p.close.time.Substring(0, 2) + ":" + p.close.time.Substring(2, 2) : "23:59"
                    })
                    .OrderBy(r => r.start)
                    .ToList()
        })
        .ToList();

    // fill in missing days
    for (int i = 0; i < 7; i++)
    {
        if (!list.Any(m => m.day == i))
            list.Add(new OpenCloseDaysModel { day = i, is_open = false, range = null });
    }

    // sort days with Sunday at the end and return the serialized result
    var settings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };
    return JsonConvert.SerializeObject(list.OrderBy(m => m.day > 0 ? m.day : 7), settings);   
}

小提琴:https://dotnetfiddle.net/lojcg1